Forum > General

Use HeapTrc

(1/2) > >>

jollytall:
I have some nasty memory leak in a rather complex project. I try to use HeapTrc but cannot understand the output.

first I had 7 leaks (when the program did nothing - using it increases the leaks, but I try to minimise the impact):
690 memory blocks allocated : 108423/110000
683 memory blocks freed     : 107959/109536
7 unfreed memory blocks : 464
True heap size : 196608
True free heap : 194560
Should be : 194800
Call trace for block $00007F2A2ED55F00 size 24
Call trace for block $00007F2A2ED55E00 size 32
Call trace for block $00007F2A2ED6B400 size 152
Call trace for block $00007F2A2ED55D00 size 24
Call trace for block $00007F2A2ED55700 size 32
Call trace for block $00007F2A2ED6B280 size 152
Call trace for block $00007F2A2ED51D00 size 48

Then I found one of them (an Indy10 "planned" leak, but I could "fix" it). Then the output:
614 memory blocks allocated : 104247/105592
608 memory blocks freed     : 103831/105176
6 unfreed memory blocks : 416
True heap size : 196608
True free heap : 194816
Should be : 195040
Call trace for block $00007F657AB3EB00 size 24
Call trace for block $00007F657AB3EA00 size 32
Call trace for block $00007F657AB54400 size 152
Call trace for block $00007F657AB3E800 size 24
Call trace for block $00007F657AB3E700 size 32
Call trace for block $00007F657AB54280 size 152

What I understand:
I have 6 leaks, at the listed memory addresses and sizes. This adds up nicely to the 6 unfreed line.

What I do not understand:
Where are these blocks reserved? I do not see any line number, although -gl is set through Lazarus Project Options checkbox (not the command line).
What is the meaning of the extra output lines (True heap size, True free heap and Should be?
The True Heap size remained the same (that is logic), but the True free heap increased by 256 bytes, although the fixed leak is only 48 bytes (one object instance).
The Should be field increased by 240 bytes. I would think that the Should be is always the True heap size minus some bytes used for program start (I read it somewhere). But stopping one leak does not explain to me the increase of it.

Martin_fr:
Your OS?

Do you get this output on the console? Or in a pop-up window, when your app closes?

It's a bit strange. Normally after each line "Call trace for ..." there should be an actual trace, like:

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---    $00000001001464CD  Notify,  line 288 of lazclasses.pas    $00000001000DB826  DELETE,  line 746 of ../objpas/classes/lists.inc    $00000001000DB7B7  CLEAR,  line 735 of ../objpas/classes/lists.inc    $00000001000DB4A8  DESTROY,  line 657 of ../objpas/classes/lists.inc    $0000000100013079  FREE,  line 336 of ../inc/objpas.incSometimes the filenames and lines are missing, then debug info needs to be added (and if debug info is there, the IDE may be able to resolve address only lines, but that is a topic for when you have addresses (not for the "block", but for the callstack where the leak happened).

Normally addresses are even listed, if this happens in the kernel. Or OS libraries.

Though, I can only speak for Win and Linux.
It all depends on what FPC supports for your OS. ( Your FPC version? )

No idea why you do not get traces...
- But you did use -gh ?
- You did not do "uses heaptrc" (in any of your units, or any unit that is somehow ending up in your app).
- You also have not chosen a different mem-manager? Like "CMem" ?


In any case, make sure you have "debug info" enabled (ideally dwarf, if supported for your OS, eg Win, Linux). -gw
Also, specify -gl

If you are on Linux (and have debug info enabled) you can try  (maybe add a logfile too)

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---valgrind --tool=memcheck yourappThis does not actually need heaptrc / -gh // But it needs debug info too (dwarf)

jollytall:
Thanks,

I am on Linux/Debian/10-Buster; FPC3.2.0; Lazarus 2.0.12.
It is a console app and tried it normally from a console and also directly from Lazarus (Ctrl-Alt-O) with the same result.
I set all debug options in Lazarus. Tried debug Automatic (-g) and Dwarf3beta (-gw3). Also set Line numbers (-gl) and Heaptrc (-gh) here. I also played around with the other options, but always the same.
I don't have Hapetrc anywhere inside (or I would see something even when I switch off -gh). cmem might be there in an Indy or C (e.g. cthreads) library somewhere, but not sure. Is there a way to check it, other than going through tens of libraries?

Btw. in some other cases, in the same program earlier, I saw the place where the guilty code was called from, or at least a line number/procedure name, even if it was very likely not correct.

With a lot of playing around (deleting code parts, etc.) finally I found these leaks. One (2X) was because an object instance in a field of another global variable object instance was not Free-d, the other two (again 2X) were because somewhere in the chain these two global variables Destroy inherit sequence was cut and two fields of an ancestor object were not freed.
This was only the tip of the iceberg, because if I used the program (i.e. not only start-stop) I had many more leaks (few hundred bytes once at the end from a global variable would not bother) gradually eating up the available memory to OOM. Now, with the same try and error mechanism I could find them all. Now my code is 0 leak!

Still it bothers me, why I could not use Heaptrc to find not only the leak, but its source as well. Also, why the "Should be" and "True free heap" changed so strange when one leak was stopped.

And still no happy end. Although I have no memory leak, my VIRT memory usage (as seen in top) is skyrocketing and I cannot find the reason for that. I know this is another problem (or according to some, not even a problem) but I would like to understand.

Thaddy:
Two remarks:
1, HOW do you use heaptrace? See wiki. Just in case https://wiki.freepascal.org/heaptrc
2. The better compiler option is -glh, so you will get the line numbers if available.

1) is because heaptrc is often used wrong. (I am not saying YOU use it wrong!)

jollytall:
Thanks Thaddy,

1) I read many times the linked wiki article and many other places. I do not think I use it wrong, but happy to investigate any idea what you might have, where I do something wrong. Btw. the wiki has zero hits on "Should be" or "True free heap", so it is surely not a help to understand those numbers.

2) I would assume that if I click in Lazarus the two boxes, and those add -gl and -gh to the making of the executable then it should be equivalent of combining the two options in one -glh. Is it not the case with fpc?

P.S. I found why the VIRT memory usage goes up constantly but I still cannot stop it. I ask it in a separate thread, just to keep some order (it is threads not releasing virtual memory when they exit - sort of "normal" procedure).

Navigation

[0] Message Index

[#] Next page

Go to full version