From a269244670efbe2250c888476aa090bb8fa1415c Mon Sep 17 00:00:00 2001 From: Paulo Meira <10246101+PMeira@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:53:09 -0300 Subject: [PATCH] Check for null pointers in a few more places, avoiding crashes (mostly with new OpenDSS users) --- src/CAPI/CAPI_Transformers.pas | 9 +++------ src/Common/Circuit.pas | 5 +++++ src/Common/CktElement.pas | 3 +++ src/PDElements/AutoTrans.pas | 14 ++++++++++++++ src/PDElements/Reactor.pas | 9 +++++++++ src/PDElements/Transformer.pas | 5 ++++- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/CAPI/CAPI_Transformers.pas b/src/CAPI/CAPI_Transformers.pas index 20565cc47..97854e43d 100644 --- a/src/CAPI/CAPI_Transformers.pas +++ b/src/CAPI/CAPI_Transformers.pas @@ -494,7 +494,7 @@ procedure Transformers_Get_WdgVoltages(var ResultPtr: PDouble; ResultCount: PAPI var elem: TObj; begin - if not _activeObj(DSSPrime, elem) then + if (not _activeObj(DSSPrime, elem)) or MissingSolution(DSSPrime) then begin DefaultResult(ResultPtr, ResultCount); Exit; @@ -521,7 +521,7 @@ procedure Transformers_Get_WdgCurrents(var ResultPtr: PDouble; ResultCount: PAPI elem: TObj; NumCurrents: Integer; begin - if not _activeObj(DSSPrime, elem) then + if (not _activeObj(DSSPrime, elem)) or MissingSolution(DSSPrime) then begin DefaultResult(ResultPtr, ResultCount); Exit; @@ -594,7 +594,7 @@ procedure Transformers_Get_LossesByType(var ResultPtr: PDouble; ResultCount: PAP CResult: PComplexArray; // this array is one-based, see DSSUcomplex elem: TObj; begin - if not _activeObj(DSSPrime, elem) then + if (not _activeObj(DSSPrime, elem)) or MissingSolution(DSSPrime) then begin DefaultResult(ResultPtr, ResultCount); Exit; @@ -602,9 +602,6 @@ procedure Transformers_Get_LossesByType(var ResultPtr: PDouble; ResultCount: PAP DSS_RecreateArray_PDouble(ResultPtr, ResultCount, 2 * 3); - if not elem.Enabled then - Exit; - CResult := PComplexArray(ResultPtr); elem.GetLosses(CResult[1], CResult[2], CResult[3]); // Keep the results in VA (NOT kVA) for consistency with CktElement_Get_Losses diff --git a/src/Common/Circuit.pas b/src/Common/Circuit.pas index d88a95522..aecb062bf 100644 --- a/src/Common/Circuit.pas +++ b/src/Common/Circuit.pas @@ -2266,6 +2266,11 @@ function TDSSCircuit.Get_Losses: Complex; begin // Return total losses in all PD Elements Result := 0; + if (Solution.NodeV = NIL) then + begin + Exit; + end; + for pdelem in PDElements do begin if pdelem.enabled then diff --git a/src/Common/CktElement.pas b/src/Common/CktElement.pas index e5dfcaded..d0d4c69d7 100644 --- a/src/Common/CktElement.pas +++ b/src/Common/CktElement.pas @@ -1139,6 +1139,9 @@ procedure TDSSCktElement.ComputeVterminal; nref: PInteger; nv0, nv: PDouble; begin + if NodeRef = NIL then + Exit; + vterm := PDouble(VTerminal); nref := PInteger(NodeRef); nv0 := PDouble(ActiveCircuit.solution.NodeV); diff --git a/src/PDElements/AutoTrans.pas b/src/PDElements/AutoTrans.pas index 3d7109a48..790f121cb 100644 --- a/src/PDElements/AutoTrans.pas +++ b/src/PDElements/AutoTrans.pas @@ -1535,6 +1535,9 @@ procedure TAutoTransObj.GetAllWindingCurrents(CurrBuffer: pComplexArray); ITerm_NL: pComplexArray; begin + if (not Enabled) or (NodeRef = NIL) or (ActiveCircuit.Solution.NodeV = NIL) then + Exit; + try Vterm := Allocmem(SizeOf(Complex) * 2 * NumWindings); Iterm := Allocmem(SizeOf(Complex) * 2 * NumWindings); @@ -1604,6 +1607,9 @@ procedure TAutoTransObj.GetWindingVoltages(iWind: Integer; VBuffer: pComplexArra var i, ii, k, NeutTerm: Integer; begin + if (not Enabled) or (NodeRef = NIL) or (ActiveCircuit.Solution.NodeV = NIL) then + Exit; + try // return Zero if winding number improperly specified if (iWind < 1) or (iWind > NumWindings) then @@ -1669,6 +1675,14 @@ procedure TAutoTransObj.GetLosses(var TotalLosses, LoadLosses, NoLoadLosses: Com cTempIterminal: pComplexArray; i: Integer; begin + if (not FEnabled) or (NodeRef = NIL) then + begin + TotalLosses := 0; + LoadLosses := 0; + NoLoadLosses := 0; + Exit; + end; + // Calculates losses in watts, vars TotalLosses := Losses; // Side effect: computes Iterminal diff --git a/src/PDElements/Reactor.pas b/src/PDElements/Reactor.pas index 76fd63a71..37611dcfa 100644 --- a/src/PDElements/Reactor.pas +++ b/src/PDElements/Reactor.pas @@ -1019,8 +1019,17 @@ procedure TReactorObj.GetLosses(var TotalLosses, LoadLosses, NoLoadLosses: Compl i: Integer; v: Complex; begin + if (not FEnabled) or (NodeRef = NIL) then + begin + TotalLosses := 0; + LoadLosses := 0; + NoLoadLosses := 0; + Exit; + end; + // Only report No Load Losses if Rp defined and Reactor is a shunt device; // Else do default behavior. + if (RpSpecified and IsShunt and (Rp <> 0.0)) then begin TotalLosses := Losses; // Side effect: computes Iterminal and Vterminal diff --git a/src/PDElements/Transformer.pas b/src/PDElements/Transformer.pas index cf00f3db2..f8f6ed8ef 100644 --- a/src/PDElements/Transformer.pas +++ b/src/PDElements/Transformer.pas @@ -1583,6 +1583,9 @@ procedure TTransfObj.GetWindingVoltages(iWind: Integer; VBuffer: pComplexArray); var i, ii, k, NeutTerm: Integer; begin + if (not Enabled) or (NodeRef = NIL) or (ActiveCircuit.Solution.NodeV = NIL) then + Exit; + // return Zero if winding number improperly specified if (iWind < 1) or (iWind > NumWindings) then begin @@ -1632,7 +1635,7 @@ procedure TTransfObj.GetLosses(var TotalLosses, LoadLosses, NoLoadLosses: Comple cTempIterminal: pComplexArray; i: Integer; begin - if not FEnabled then + if (not FEnabled) or (NodeRef = NIL) then begin TotalLosses := 0; LoadLosses := 0;