tags:

views:

239

answers:

8

Hi! Could you help me please to solve this problem. Here is my code. I Store (in this example) 10000 strings and when I try to delete them only some amount of memory is freed the rest leaks.

type
  PMyData = ^TMyData;
  TMyData = record
  Name:    string;
end;
////////

var
XList:Tlist;
//////////

// Here is how I add//
var
 MyData: PMyData;
 I:Integer;
begin
 for I:=0 to 10000 do begin
 New(MyData);
  MyData.Name:='Hello';
   XList.Add(TObject(MyData));
  end;
end;


///Here is how I delete///
var
 MyData: PMyData;
 I:Integer;
begin
 for I:= XList.Count - 1 downto 0 do begin
 MyData:=PMyData (XList[I]); /// I also used (XList.Items[I])  but the result is the same
  Dispose(MyData);
    XList.Delete(I);
end;
+3  A: 

Your code looks good. What exactly do you mean, only some memory is freed and the rest leaks? Are you getting memory leak reports from FastMM, or are you just not seeing the memory used counter in Task Manager go all the way back down?

If you're not seeing your program give all the memory back, that's by design. It keeps some of it around so that if you allocate more memory it doesn't have to ask for more back from Windows immediately, which helps improve performance. The memory is only "leaked" if the memory manager hasn't actually reclaimed it.

Mason Wheeler
OK. Thank you for help! I also believe there is no leak, but still.It is more noticeable when I add 200000 strings. For example, if I add 200000 strings for the 1st time, my app uses (according to windows Task Manager: "Mem Usage" - 15304k and "VM Size" - 13492k), I try to free the memory and now my app uses: 7616k / 5800k. If I add twice more strings (400000), my app uses now: 25480k / 23436k, and 8824k / 6768k after I free it, which is more than I had when it was freed for the 1st time (7616k / 5800k). So, is it normal, the more strings I add, the more memory seems to leak?
Serhiy
If you want to know if you're really leaking anything, put `ReportMemoryLeaksAtShutdown := true;` in your DPR and see if it reports anything when you quit the program.
Mason Wheeler
+6  A: 

I see no leak in that code. How are you determining that a leak is occuring? Are you looking at Task Manager? If so, then that is not a reliable way to detect memory leaks. The VCL memory manager does not release freed memory back to the OS, it is cached for later re-use. Task Manager displays allocated memory. It has no concept of how that memory is actually managed by applications.

Remy Lebeau - TeamB
Better said, it doesn't release *all* freed memory back to the OS.
Mason Wheeler
A: 

OK. Thank you for help! I also believe there is no leak, but still. It is more noticeable when I add 200000 strings. For example, if I add 200000 strings for the 1st time, my app uses (according to windows Task Manager: "Mem Usage" - 15304k and "VM Size" - 13492k), I try to free the memory and now my app uses: 7616k / 5800k. If I add twice more strings (400000), my app uses now: 25480k / 23436k, and 8824k / 6768k after I free it, which is more than I had when it was freed for the 1st time (7616k / 5800k). So, is it normal, the more strings I add, the more memory seems to leak?

Serhiy
Hi Serhiy! I didn't downvote you, but you should post a comment instead of posting an answer that ISN'T really an answer.
Smasher
Ok. This is the 1st time I wrote here.
Serhiy
HI. I still need your help! I tried to add ass much strings as possible and I hoped that my app keeps the strings in memory for later use, and it would free the memory when needed, instead it just used all available memory. But, I found the right way to solve this problem. In my code I used - XList.Delete(I); but it turned out that it did not delete any item. So instead I used XList.Clear. And it worked. No matter how many strings I add, I can fully free the memory. Could you tell me please, is there a bug in "XList.Delete(I)" procedure?
Serhiy
+4  A: 

Windows task manager isn't a reliable measure of memory use. Use the FastMM4 memory manager with leak tracing turned on.

Loren Pechtel
+5  A: 

As far as I can tell, this code is not leaking, provided you effectively execute the clean up code.
The only way to tell if your code is leaking is by asking the Memory Manager to report any leak by adding this instruction somewhere in your code (be sure it's executed):

 ReportMemoryLeaksOnShutdown := True;

The Memory Manager will tell if any of the memory requested by your code is not freed when the application terminates, i.e. YOUR CODE has a leak.
After that, it is the Memory Manager's job to give back the memory to the OS upon termination, and it does it correctly.

Now as to why TaskManager reports more memory apparently not freed when the number of strings increases, it's because the Memory Manager does not relinquish all previously requested memory to the OS as soon as the strings are freed, in case it's needed again later; to avoid requesting again from the OS, it keeps it.

As stated in other answers, TaskManager is not a good tool to spot memory leaks...

François
Thank you very much! There is no leak. When I add strings and then clear them The Memory Manager keeps quiet, but when I add without clearing it says thet there is a memory leak. So everything is ok. Thank you!
Serhiy
A: 

Call below function before Dispose or change record to class(TObject)

Finalize(MyData^);

Cheers

Pham
Dispose does the Finalize for you, so calling Finalize is not necessary.
The_Fox
A: 

Anytime a record pointer contains a Variant Unbound array such as ... array of ... string except short string type interface you need to call Finalize to free such data before doing a FreeMem or Dispose. Otherwise use class is better

Cheers

Pham
A: 

Try:

FreeAndNil(XList.Items[I]); 
XList.Delete(I);
Eduardo
Ok. Tried it but that won't work. The only way out I found is to use XList.Clear, but in this way all the list is cleared, but what if I need to delete only some items. not all of them? XList.Delete(I) does not work, it just deletes an item in the TList but does not free the memory? Though XList.Clear does delete the items and free the memory!!!
Serhiy
No. I get an error: Constant object can not be passed as var parameter. If I do MyData:=PMyData (XList[I]);/////FreeAndNil(MyData); instead of your variant, it works, but only once. If I try to add strings one more time I get Errors.
Serhiy