I just can't figure out this memory leak that EurekaLog is reporting for my program. I'm using Delphi 2009. Here it is:
Memory Leak: Type=Data; Total size=26; Count=1;
The stack is:
System.pas _UStrSetLength 17477
System.pas _UStrCat 17572
Process.pas InputGedcomFile 1145
That is all there is in the stack. EurekaLog is pointing me to the location where the memory that was not released was first allocated. According to it, the line in my program is line 1145 of InputGedcomFile. That line is:
CurStruct0Key := 'HEAD' + Level0Key;
where CurStruct0Key and Level0Key are simply defined in the procedure as local variables that should be dynamically handled by the Delphi memory manager when entering and leaving the procedure:
var CurStruct0Key, Level0Key: string;
So now I look at the _UStrCat procedure in the System Unit. Line 17572 is:
CALL _UStrSetLength // Set length of Dest
and I go to the _UStrSetLength procedure in the System Unit, and the relevant lines are:
@@isUnicode:
CMP [EAX-skew].StrRec.refCnt,1 // !!! MT safety
JNE @@copyString // not unique, so copy
SUB EAX,rOff // Offset EAX "S" to start of memory block
ADD EDX,EDX // Double length to get size
JO @@overflow
ADD EDX,rOff+2 // Add string rec size
JO @@overflow
PUSH EAX // Put S on stack
MOV EAX,ESP // to pass by reference
CALL _ReallocMem
POP EAX
ADD EAX,rOff // Readjust
MOV [EBX],EAX // Store
MOV [EAX-skew].StrRec.length,ESI
MOV WORD PTR [EAX+ESI*2],0 // Null terminate
TEST EDI,EDI // Was a temp created?
JZ @@exit
PUSH EDI
MOV EAX,ESP
CALL _LStrClr
POP EDI
JMP @@exit
where line 17477 is the "CALL _ReallocMem" line.
So then what is the memory leak? Surely a simple concatenate of a string constant to a local string variable should not be causing a memory leak.
Why is EurekaLog pointing me to the ReallocMem line in a _UStrSetLength routine that is part of Delphi?
This is Delphi 2009 and I am using the new unicode strings.
Any help or explanation here will be much appreciated.
Solution found:
The string was being assigned to an attribute of a new menu item. The menu item was added to the menu. Then the new menu item was freed, and thus I thought everything was cleaned up. Because the string (via reference counting) was still being used because it was copied to the item, the string was not freed in memory, even though it was introduced as a local variable in the routine.
Normally this shouldn't have been a leak. However, my program at times deletes various menu items with "menu.item.delete(i)". What I didn't realize was that the delete does not free the memory of the item itself. Therefore that reference-counted string did not get freed, thus causing the leak.
The solution was to change my "menu.item.delete(i)" statements into: "menu.item[i].free".