Tracked down two more memory leaks coming from ext2spice, due to

client data generated by ext2spice and attached to a node's
nodeClient record;  there is an initNodeClient() routine but no
corresponding freeNodeClient() routine.  Eventually had to add a
callback function passed to EFDone() and EFFlatDone() to clean up
these entries.  After doing that, valgrind reports clean for all
memory allocated within ext2spice (there are other things that are
not freed but not related to a specific command, so do not need to
be treated as leaks).
This commit is contained in:
Tim Edwards 2021-12-13 18:05:53 -05:00
parent 7297ca079f
commit 5e3c26c95a
8 changed files with 69 additions and 20 deletions

View File

@ -638,8 +638,8 @@ runexttosim:
(void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy);
EFVisitNodes(simnodeVisit, (ClientData) NULL);
EFFlatDone();
EFDone();
EFFlatDone(NULL);
EFDone(NULL);
if (esSimF) fclose(esSimF);
if (esLabF) fclose(esLabF);
@ -766,8 +766,8 @@ main(argc, argv)
(void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy);
EFVisitNodes(simnodeVisit, (ClientData) NULL);
EFFlatDone();
EFDone();
EFFlatDone(NULL);
EFDone(NULL);
if (esSimF) fclose(esSimF);
if (esLabF) fclose(esLabF);

View File

@ -1884,7 +1884,7 @@ esHierVisit(hc, cdata)
if ((def != topdef) && (hc->hc_use->use_def->def_flags & DEF_NODEVICES) &&
(!doStub))
{
EFFlatDone();
EFFlatDone(esFreeNodeClient);
return 0;
}
else if (doStub)
@ -1987,7 +1987,7 @@ esHierVisit(hc, cdata)
#endif
}
EFFlatDone();
EFFlatDone(esFreeNodeClient);
return 0;
}

View File

@ -113,6 +113,34 @@ int esSpiceDevsMerged;
devMerge *devMergeList = NULL ;
/*
* ----------------------------------------------------------------------------
*
* esFreeNodeClient ---
*
* Free the string spiceNodeName associated with the nodeClient
* record that ext2spice allocates per each node structure.
*
* Returns:
* 0 always.
*
* Side effects:
* Frees an allocated string.
*
* ----------------------------------------------------------------------------
*/
int
esFreeNodeClient(client)
nodeClient *client;
{
if (client != (ClientData)NULL)
if (client->spiceNodeName != NULL)
freeMagic((char *)client->spiceNodeName);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -1002,9 +1030,9 @@ runexttospice:
if (esFormat == HSPICE)
printSubcktDict();
EFFlatDone();
EFFlatDone(esFreeNodeClient);
}
EFDone();
EFDone(esFreeNodeClient);
if (esFormat == HSPICE) {
HashKill(&subcktNameTable);
#ifndef UNSORTED_SUBCKT
@ -1167,8 +1195,8 @@ main(argc, argv)
if (esFormat == HSPICE)
printSubcktDict();
EFFlatDone();
EFDone();
EFFlatDone(esFreeNodeClient);
EFDone(esFreeNodeClient);
if (esFormat == HSPICE) {
HashKill(&subcktNameTable);
#ifndef UNSORTED_SUBCKT

View File

@ -36,6 +36,7 @@ extern EFNode *spcdevHierSubstrate();
extern char *nodeSpiceHierName();
extern devMerge *mkDevMerge();
extern bool extHierSDAttr();
extern int esFreeNodeClient();
extern bool devIsKilled();
extern float getCurDevMult();

View File

@ -1988,18 +1988,30 @@ efFreeNodeTable(table)
* Free the circular list of nodes of which 'head' is the head.
* Don't free 'head' itself, since it's statically allocated.
*
* If the client (e.g., ext2spice, ext2sim, ...) allocates memory for a
* node, then that client needs to provide a function "func" of the form:
*
* int func(client)
* ClientData client;
* {
* }
*
* The return value is unused but should be zero for consistency.
*
* Results:
* None.
*
* Side effects:
* Frees memory.
* Frees memory. Calls func() to free additional memory allocated
* in the node structure by a client.
*
* ----------------------------------------------------------------------------
*/
void
efFreeNodeList(head)
efFreeNodeList(head, func)
EFNode *head;
int (*func)();
{
EFNode *node;
EFAttr *ap;
@ -2010,6 +2022,12 @@ efFreeNodeList(head)
{
for (ap = node->efnode_attrs; ap; ap = ap->efa_next)
freeMagic((char *) ap);
if (node->efnode_client != (ClientData)NULL)
{
if (func != NULL)
(*func)(node->efnode_client);
freeMagic((char *)node->efnode_client);
}
freeMagic((char *) node);
}
}

View File

@ -81,7 +81,7 @@ EFInit()
*
* EFDone --
*
* Overall cleanup.
* Overall cleanup. For use of func(), see efFreeNodeList() in EFbuild.c.
*
* Results:
* None.
@ -95,7 +95,8 @@ EFInit()
*/
void
EFDone()
EFDone(func)
int (*func)();
{
Connection *conn;
HashSearch hs;
@ -111,7 +112,7 @@ EFDone()
def = (Def *) HashGetValue(he);
freeMagic(def->def_name);
efFreeNodeTable(&def->def_nodes);
efFreeNodeList(&def->def_firstn);
efFreeNodeList(&def->def_firstn, func);
efFreeUseTable(&def->def_uses);
efFreeDevTable(&def->def_devs);
HashKill(&def->def_nodes);

View File

@ -240,7 +240,7 @@ EFFlatBuildOneLevel(def, flags)
* EFFlatDone --
*
* Cleanup by removing all memory used by the flattened circuit
* representation.
* representation. For use of func(), see efFreeNodeList() in EFbuild.c.
*
* Results:
* None.
@ -252,7 +252,8 @@ EFFlatBuildOneLevel(def, flags)
*/
void
EFFlatDone()
EFFlatDone(func)
int (*func)();
{
#ifdef MALLOCTRACE
/* Hash table statistics */
@ -262,7 +263,7 @@ EFFlatDone()
/* Free temporary storage */
efFreeNodeTable(&efNodeHashTable);
efFreeNodeList(&efNodeList);
efFreeNodeList(&efNodeList, func);
HashFreeKill(&efCapHashTable);
HashKill(&efNodeHashTable);
HashKill(&efDistHashTable);

View File

@ -2172,8 +2172,8 @@ DefWriteCell(def, outName, allSpecial, units)
fprintf(f, "END NETS\n\n");
if (nets.has_nets) {
EFFlatDone();
EFDone();
EFFlatDone(NULL);
EFDone(NULL);
}
fprintf(f, "END DESIGN\n\n");