From 9d9e0996ab3646653d9a2b5517e28d586a368ae6 Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Sat, 30 Sep 2023 17:01:53 -0400 Subject: [PATCH 1/5] Leak check enabled; fixed timer leaks --- src/cse.cpp | 4 +++- src/dmpak.cpp | 18 ++++++++++++++++++ src/dmpak.h | 1 + src/timer.cpp | 22 ++++++++++++++-------- src/timer.h | 2 +- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/cse.cpp b/src/cse.cpp index 03f185646..1c96327de 100644 --- a/src/cse.cpp +++ b/src/cse.cpp @@ -356,6 +356,8 @@ _DLLImpExp int cse( // CSE main function, called by console main(), Windows Wi pMsgCallBack = _pMsgCallBack; #endif // CSE_DLL + dmInitMemoryChecking(); + isCallBackAbort = 0; // clear abort flag (1 if prior run aborted) //-- nested entry protection: DLL only has 1 copy of variables even if 2 copies of app loaded @@ -1224,7 +1226,7 @@ LOCAL INT cse3( INT argc, const char* argv[]) vrPrintf( vrTimes, "\n\n%sTiming info --\n\n", pfx); int tmrLimit = (TestOptions & 2) ? TMR_COUNT : TMR_TOTAL + 1; for (i = 0; i < tmrLimit; i++) - vrTmrDisp( vrTimes, i, pfx); // timer.cpp + tmrVrDisp( vrTimes, i, pfx); // timer.cpp } // Output timing info & any remaining log/err msgs to report file -- in particular, input error that prevented unspool above. diff --git a/src/dmpak.cpp b/src/dmpak.cpp index dd753fc40..7939ac477 100644 --- a/src/dmpak.cpp +++ b/src/dmpak.cpp @@ -199,6 +199,24 @@ RC dmIncRef( DMP* pp, int erOp/*=ABT*/) // duplicate block or ++ref count (as im dmRefCount( *pp)++; return RCOK; } // dmIncRef +//----------------------------------------------------------------------------- +void dmInitMemoryChecking() +{ + +#if CSE_COMPILER == CSE_COMPILER_MSVC + // Get the current bits + int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + + tmp |= _CRTDBG_LEAK_CHECK_DF; // check for memory leaks at program exit + + // Set the new bits + _CrtSetDbgFlag(tmp); + + int request = -1; + if (request != -1) + _CrtSetBreakAlloc(request); +#endif +} // dmInitMemoryChecking /////////////////////////////////////////////////////////////////////////////// // end of dmpak.cpp diff --git a/src/dmpak.h b/src/dmpak.h index 15bdabbb7..7ebd063ed 100644 --- a/src/dmpak.h +++ b/src/dmpak.h @@ -39,6 +39,7 @@ RC dmfree( DMP *pp); // checks stack, no FC RC dmIncRef( DMP *pp, int erOp=ABT); RC dmPrivateCopy( DMP *pp, int erOp=ABT); int dmIsGoodPtr( DMP p, const char* s, int erOp); +void dmInitMemoryChecking(); #ifdef DEBUG2 void FC dmeatmem( USI sz); diff --git a/src/timer.cpp b/src/timer.cpp index 651778cc2..eadaf73a1 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -18,12 +18,18 @@ struct TMRDATA int tcalls; // # of calls LLI tbeg; // time at beg of current timing, ticks LLI ttot; // total time for timer, ticks - WStr tname; // name of timer - TMRDATA(const char* _tname = "") : tcalls(0), tbeg(0), ttot(0), tname(_tname) + std::string tname; // name of timer + TMRDATA() : tcalls(0), tbeg(0), ttot(0), tname() {} -}; -static WVect< TMRDATA> tmrtab; -//------------------------------------------------------------------------------ + void tmrSet(const char* tmrName) + { tname = tmrName; + tcalls = 0; + tbeg = ttot = 0; + } // TMRDATA::tmrSet +}; // struct TMRDATA +//----------------------------------------------------------------------------- +static std::vector< TMRDATA> tmrtab; +//----------------------------------------------------------------------------- static double tmrSecsPerTick = -1.; //----------------------------------------------------------------------------- static double tmrTicksToSecs( @@ -115,7 +121,7 @@ void tmrInit( // Initialize (but do *NOT* start) a timer { if (size_t( tmr) >= tmrtab.size()) tmrtab.resize(tmr+5); - new (&tmrtab[ tmr]) TMRDATA(tmrName); + tmrtab[tmr].tmrSet(tmrName); tmrSetupIf(); // constants etc if needed } // tmrInit //======================================================================== @@ -164,7 +170,7 @@ void tmrdisp( // Display current data for a timer } // tmrdisp #endif //======================================================================== -RC vrTmrDisp( // Display current data for a timer +RC tmrVrDisp( // Display current data for a timer int vrh, // open virtual report to which to display results int tmr, // Timer number @@ -180,6 +186,6 @@ RC vrTmrDisp( // Display current data for a timer return vrPrintf( vrh, "%s%20s: Time = %-7.2f Calls = %-8ld T/C = %-0.4f\n", pfx, tmrtab[tmr].tname.c_str(), t, tmrtab[tmr].tcalls, t/nc ); -} // vrTmrDisp +} // tmrVrDisp // end of timer.cpp diff --git a/src/timer.h b/src/timer.h index b8bed9918..62dbaa915 100644 --- a/src/timer.h +++ b/src/timer.h @@ -10,7 +10,7 @@ void tmrStart( int tmr); void tmrStop( int tmr); double tmrCurTot( int tmr); void tmrDisp( FILE *f, int tmr, double delta); // may be if 0'd -RC vrTmrDisp( int vrh, int tmr, const char* pfx="", double delta=0.); +RC tmrVrDisp( int vrh, int tmr, const char* pfx="", double delta=0.); // End of timer.h From 7c30f95081c788aa89e256a26533262ccd1dc450 Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Sun, 1 Oct 2023 16:33:03 -0400 Subject: [PATCH 2/5] Fix AirNet leak --- src/cgcomp.cpp | 8 +++++++- src/dmpak.cpp | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cgcomp.cpp b/src/cgcomp.cpp index 32a64edb7..384f63993 100644 --- a/src/cgcomp.cpp +++ b/src/cgcomp.cpp @@ -2283,7 +2283,13 @@ struct AIRNET_SOLVER : an_pParent( pParent), an_jac(), an_V1(), an_V2(), an_mdotAbs(nullptr), an_didLast(nullptr), an_nz( 0) { } - ~AIRNET_SOLVER() { } + ~AIRNET_SOLVER() + { + delete an_mdotAbs; + an_mdotAbs = nullptr; + delete an_didLast; + an_didLast = nullptr; + } RC an_Calc(int iV); diff --git a/src/dmpak.cpp b/src/dmpak.cpp index 7939ac477..226ff22ed 100644 --- a/src/dmpak.cpp +++ b/src/dmpak.cpp @@ -204,6 +204,7 @@ void dmInitMemoryChecking() { #if CSE_COMPILER == CSE_COMPILER_MSVC +#if defined( _DEBUG) // Get the current bits int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); @@ -212,10 +213,11 @@ void dmInitMemoryChecking() // Set the new bits _CrtSetDbgFlag(tmp); - int request = -1; + int request = -1; // set with debugger to trap specific blocks if (request != -1) _CrtSetBreakAlloc(request); #endif +#endif } // dmInitMemoryChecking /////////////////////////////////////////////////////////////////////////////// From 4b682a8048f6e46c8de83da6059e7ed301c20ae1 Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Mon, 2 Oct 2023 09:38:37 -0400 Subject: [PATCH 3/5] Initial fix of solar memory leak --- src/cgsolar.cpp | 4 +++- src/solar.cpp | 10 +++++++--- src/solar.h | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/cgsolar.cpp b/src/cgsolar.cpp index d9f045a7b..e5575ec3c 100644 --- a/src/cgsolar.cpp +++ b/src/cgsolar.cpp @@ -97,6 +97,8 @@ RC TOPRAT::tp_LocInit() // location-initializer for CSE // slpak remembers its location internally. #if (SLRCALCS & 1) + slfree(Locsolar); // delete any pre-existing + Locsolar = slinit(RAD(latitude), // latitude (to radians) RAD(longitude), // longitude timeZone, // time zone @@ -111,7 +113,7 @@ RC TOPRAT::tp_LocInit() // location-initializer for CSE RC TOPRAT::tp_LocDone() // Free location related dm stuff: Locsolar { #if (SLRCALCS & 1) - slfree(&Locsolar); // free solar data struct, null ptr, slpak.cpp. Redundant call ok. + slfree(Locsolar); // free solar data struct, null ptr, slpak.cpp. Redundant call ok. #endif return RCOK; } // TOPRAT::tp_LocDone diff --git a/src/solar.cpp b/src/solar.cpp index 1ab5e8628..b3e895c9e 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -431,10 +431,14 @@ SLLOCDAT *FC slselect(/* Sets current solar/location data to that given by arg * //====================================================================== void FC slfree( // Free a SLLOCDAT structure - SLLOCDAT **ppSlr) // ptr to ptr. nop if ptr is NULL; ptr is set NULL: redundant calls ok. + SLLOCDAT* &pSlr) // nop if ptr is NULL; ptr is set NULL: redundant calls ok. { - delete *ppSlr; // free heap storage occupied by object - *ppSlr = NULL; // erase no-longer-valid pointer + SLLOCDAT* pSlrSave = pSlr; + delete pSlr; // free heap storage occupied by object + pSlr = nullptr; // erase no-longer-valid pointer + if (slloccur == pSlrSave) + slloccur = nullptr; + } // slfree //====================================================================== diff --git a/src/solar.h b/src/solar.h index d5b6ced31..21018f672 100644 --- a/src/solar.h +++ b/src/solar.h @@ -120,7 +120,7 @@ void FC slsdc(float azm, float tilt, float dcos[3]); float slVProfAng(float relAzm, float cosZen); SLLOCDAT* FC slinit(float rlat, float rlong, float tzn, float siteElev); SLLOCDAT* FC slselect(SLLOCDAT* pSlr); -void FC slfree(SLLOCDAT** ppSlr); +void FC slfree(SLLOCDAT* &pSlr); void FC slday(DOY doy, int timetype, int options = 0); void FC sldec(float sldec, int timetype); int slsurfhr(float sdircos[3], int ihr, float* pCosi, float* pAzm = NULL, From c2416d6ee45af354871fb931ece2853eddea2c85 Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Mon, 2 Oct 2023 09:54:45 -0400 Subject: [PATCH 4/5] Eliminate duplicate pointer to SLLOCDAT --- src/cgsolar.cpp | 10 ++++------ src/solar.cpp | 51 +++++++++++++++++-------------------------------- src/solar.h | 5 ++--- 3 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/cgsolar.cpp b/src/cgsolar.cpp index e5575ec3c..93b07f5b2 100644 --- a/src/cgsolar.cpp +++ b/src/cgsolar.cpp @@ -76,7 +76,7 @@ int slrCalcJDays[13] = // julian day of year for which to do solar table calcula //16 14 15 14 14 10 16 15 15 15 14 10 (days of months) }; -#if (SLRCALCS & 1) +#if (0 && SLRCALCS & 1) static SLLOCDAT* Locsolar = NULL; // Ptr to solar info structure for current calculation. // Released by slfree from tp_LocDone(). // Address saved by slinit for other slpak calls. @@ -97,9 +97,7 @@ RC TOPRAT::tp_LocInit() // location-initializer for CSE // slpak remembers its location internally. #if (SLRCALCS & 1) - slfree(Locsolar); // delete any pre-existing - - Locsolar = slinit(RAD(latitude), // latitude (to radians) + slinit(RAD(latitude), // latitude (to radians) RAD(longitude), // longitude timeZone, // time zone elevation); // site altitude (ft) @@ -113,7 +111,7 @@ RC TOPRAT::tp_LocInit() // location-initializer for CSE RC TOPRAT::tp_LocDone() // Free location related dm stuff: Locsolar { #if (SLRCALCS & 1) - slfree(Locsolar); // free solar data struct, null ptr, slpak.cpp. Redundant call ok. + slfree(); // free solar data struct, null ptr, slpak.cpp. Redundant call ok. #endif return RCOK; } // TOPRAT::tp_LocDone @@ -386,7 +384,7 @@ void FC makHrSgt( // make solar tables for an hour for current month * INT(Top.tp_date.month-1), INT(slrCalcJDays[Top.tp_date.month]) ); #endif -// Initialize slpak for a standard day near middle of month. slselect(Locsolar) in effect. Note restored at exit. +// Initialize slpak for a standard day near middle of month. Note restored at exit. slday( slrCalcJDays[ Top.tp_date.month], // julian date for this month's solar calcs sltmLST ); // say use local standard time diff --git a/src/solar.cpp b/src/solar.cpp index b3e895c9e..1fa3d4792 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -143,7 +143,7 @@ const float SolarConstant = 434.f; // previous value, source unknown // pointer to current solar/location info thing. Set by slinit() / slselect(). // Used by slday(), sldec, slsurfhr, slha, sldircos, slaniso -LOCAL SLLOCDAT * slloccur; +static SLLOCDAT* slloccur = nullptr; /*----------------------- LOCAL FUNCTION DECLARATIONS ---------------------*/ @@ -385,15 +385,14 @@ float slVProfAng( // vertical profile angle return profAng; } // slVProfAng //====================================================================== -SLLOCDAT *FC -slinit(/* Allocate, init, and select a SLLOCAT structure */ +void slinit(/* Allocate, init, and select a SLLOCAT structure */ - float rlat, // latitude, +=N, radians - float rlong, // longitude, +=W (non-standard), radians - float tzn, // time zone (hrs west of GMT. EST=5, PST=8, etc. ) - float siteElev) // site elevation (ft above sea level). - // Used only with global/direct functions (eg dirsimx.c, gshift.c) - // SO passing 0 is generally harmless. + float rlat, // latitude, +=N, radians + float rlong, // longitude, +=W (non-standard), radians + float tzn, // time zone (hrs west of GMT. EST=5, PST=8, etc. ) + float siteElev) // site elevation (ft above sea level). + // Used only with global/direct functions (eg dirsimx.c, gshift.c) + // SO passing 0 is generally harmless. /* Returns pointer to SLLOCDAT structure initialized for specified location. This location is now also the current location for subsequent @@ -411,33 +410,19 @@ slinit(/* Allocate, init, and select a SLLOCAT structure */ pSlr->tzn = tzn; /* time zone, hours west of GMT */ pSlr->siteElev = siteElev; /* site elevation, ft */ pSlr->pressureRatio = (float)exp(-0.0001184 * 0.3048 * siteElev); - /* site pressure ratio: nominal ratio of surface pressure to sea level pressure. - Formula appears in Perez code (dirsim.c) and is documented in SERI Consensus - Summary (full reference above), p. 17. - NOTE: needs reconciliation with psychro1.c:psyAltitude. 8-9-90 */ - return slselect( - pSlr); // make current: ptr for other slpak fcns. ret ptr, for later slselects and slfree -} // slinit -//====================================================================== -SLLOCDAT *FC slselect(/* Sets current solar/location data to that given by arg */ - - SLLOCDAT *pSlr) /* pointer returned by an earlier slinit call */ - -/* returns pSlr as convenience (new feature 8-9-90) */ -{ - return (slloccur = pSlr); /* set file-global for slpak fcns to use */ -} /* slselect */ + // site pressure ratio: nominal ratio of surface pressure to sea level pressure. + // Formula appears in Perez code (dirsim.c) and is documented in SERI Consensus + // Summary (full reference above), p. 17. + // NOTE: needs reconciliation with psychro1.c:psyAltitude. 8-9-90 + slfree(); + slloccur = pSlr; // make current: ptr for other slpak fcns. ret ptr +} // slinit //====================================================================== -void FC slfree( // Free a SLLOCDAT structure - - SLLOCDAT* &pSlr) // nop if ptr is NULL; ptr is set NULL: redundant calls ok. +void FC slfree() // Free a SLLOCDAT structure { - SLLOCDAT* pSlrSave = pSlr; - delete pSlr; // free heap storage occupied by object - pSlr = nullptr; // erase no-longer-valid pointer - if (slloccur == pSlrSave) - slloccur = nullptr; + delete slloccur; // free heap storage occupied by object + slloccur = nullptr; } // slfree diff --git a/src/solar.h b/src/solar.h index 21018f672..5d61a96c3 100644 --- a/src/solar.h +++ b/src/solar.h @@ -118,9 +118,8 @@ x void FC slhourfromalt(float alt); #endif void FC slsdc(float azm, float tilt, float dcos[3]); float slVProfAng(float relAzm, float cosZen); -SLLOCDAT* FC slinit(float rlat, float rlong, float tzn, float siteElev); -SLLOCDAT* FC slselect(SLLOCDAT* pSlr); -void FC slfree(SLLOCDAT* &pSlr); +void slinit(float rlat, float rlong, float tzn, float siteElev); +void FC slfree(); void FC slday(DOY doy, int timetype, int options = 0); void FC sldec(float sldec, int timetype); int slsurfhr(float sdircos[3], int ihr, float* pCosi, float* pAzm = NULL, From 8736464e67ad82f8d690a8da9c7d7438d92f826f Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Mon, 2 Oct 2023 10:51:54 -0400 Subject: [PATCH 5/5] Fix DREF memory leak --- src/cul.cpp | 1 + src/solar.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cul.cpp b/src/cul.cpp index c2551abb7..f83228c3c 100644 --- a/src/cul.cpp +++ b/src/cul.cpp @@ -4207,6 +4207,7 @@ LOCAL void FC drefAddI( // add deferred reference table entry -- general inner drfp->i = i; // entry subscr, drfp->fn = fn; // field number. drfp->toB = toB; // what is being referenced: rat, + dmfree( DMPP( drfp->toName)); // free any prior toName before overwrite drfp->toName = strsave( toName); // entry name. drfp->defO = defO; // default owner from context // .. get file/line info for error messages using cutok.cpp fcn diff --git a/src/solar.cpp b/src/solar.cpp index 1fa3d4792..611e138a2 100644 --- a/src/solar.cpp +++ b/src/solar.cpp @@ -416,7 +416,7 @@ void slinit(/* Allocate, init, and select a SLLOCAT structure */ // NOTE: needs reconciliation with psychro1.c:psyAltitude. 8-9-90 slfree(); - slloccur = pSlr; // make current: ptr for other slpak fcns. ret ptr + slloccur = pSlr; // make current: ptr for other slpak fcns } // slinit //====================================================================== void FC slfree() // Free a SLLOCDAT structure