diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index d41ff6774..f45454bbb 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -119,6 +119,8 @@ com_quit(wordlist *wl) /* add 1000 to notify that we exit from 'quit' */ controlled_exit(1000 + exitcode); #else + /* delete all memory malloced since initialization */ + mem_delete(); exit(exitcode); #endif } diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index c9f0ba291..12992f13b 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -245,6 +245,14 @@ extern char *nexttok(const char *s); extern int get_l_paren(char **s); extern int get_r_paren(char **s); +#if defined(SHARED_MODULE) && (!defined(_MSC_VER) && !defined(__MINGW32__)) +extern void __attribute__((constructor)) mem_init(void); +extern void __attribute__((destructor)) mem_delete(void); +#else +extern void mem_init(void); +extern void mem_delete(void); +#endif + /* Some external variables */ extern char *Spice_Exec_Dir; diff --git a/src/main.c b/src/main.c index de3d0b540..68e53682b 100644 --- a/src/main.c +++ b/src/main.c @@ -846,6 +846,11 @@ main(int argc, char **argv) /* mwDoFlush(1); */ #endif +#ifndef SHARED_MODULE + /* initialize memory address storage for local gc */ + mem_init(); +#endif + /* MFB tends to jump to 0 on errors. This tends to catch it. */ { static int started = 0; diff --git a/src/misc/alloc.c b/src/misc/alloc.c index 5f8ad3916..f1a7b09d8 100644 --- a/src/misc/alloc.c +++ b/src/misc/alloc.c @@ -36,8 +36,14 @@ extern mutexType allocMutex; #endif #endif -int mem_init(void); -int mem_delete(void); +#if defined(SHARED_MODULE) && (!defined(_MSC_VER) && !defined(__MINGW32__)) +void __attribute__((constructor)) mem_init(void); +void __attribute__((destructor)) mem_delete(void); +#else +void mem_init(void); +void mem_delete(void); +#endif + static int memsaved(void *ptr); static void memdeleted(const void *ptr); @@ -208,11 +214,10 @@ tcalloc(size_t num, size_t stype) #endif /* initialize hash table to store allocated mem addresses */ -int mem_init(void) { +void mem_init(void) { memory_table = nghash_init_pointer(1024); gc_is_on = 1; return OK; - } /* add to counter and hash table if memory is allocated */ @@ -250,7 +255,7 @@ void my_key_free(void * key) } /* free hash table */ -int mem_delete(void) { +void mem_delete(void) { gc_is_on = 0; printf("mem allocated %d times, deleted %d times\n", mem_in, mem_out); nghash_free(memory_table, NULL, my_key_free); diff --git a/src/sharedspice.c b/src/sharedspice.c index fbf9fb965..c426649ee 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -1580,6 +1580,7 @@ ATTRIBUTE_NORETURN void shared_exit(int status) bgtr(fl_exited, ng_ident, userptr); // set a flag that ngspice wants to be detached ngexit(status, FALSE, coquit, ng_ident, userptr); + // finish and exit the worker thread #ifdef HAVE_LIBPTHREAD pthread_exit(NULL); @@ -1899,3 +1900,41 @@ sharedsync(double *pckttime, double *pcktdelta, double olddelta, double finalt, } } } + +/* main dll entry, used upon exiting dll */ +#if defined(_MSC_VER) || defined(__MINGW32__) +BOOL +WINAPI DllMain( + HINSTANCE hinstDLL, // handle to DLL module + DWORD fdwReason, // reason for calling function + LPVOID lpReserved) // reserved +{ + NG_IGNORE(hinstDLL); + NG_IGNORE(lpReserved); + + // Perform actions based on the reason for calling. + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + // Initialize once for each new process. + // Return FALSE to fail DLL load. + mem_init(); + break; + + case DLL_THREAD_ATTACH: + // Do thread-specific initialization. + break; + + case DLL_THREAD_DETACH: + // Do thread-specific cleanup. + break; + + case DLL_PROCESS_DETACH: + // Perform any necessary cleanup. + /* delete all memory dynamically allocated in dll */ + mem_delete(); + break; + } + return TRUE; // Successful DLL_PROCESS_ATTACH. +} +#endif