<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Part of the mystery here could be that the compiler is optimizing out the stack frame on the actual AllocMem call (which is compiled when making the compiler).<br><br>It seems that recompiling after placing {$OPTIMIZATION OFF} before GetMem in rtl/inc/heap.inc [and {$OPTIMIZATION DEFAULT} after ReallocMemory] ensures the compiler generates a stack frame for these calls. <br><br>However, it is still necessary either 1) to edit heaptrc.pp to call CaptureBacktrace with skipframes=0 or 2) to change the CaptureBacktrace function not to discard a stackframe (as shown in the original post).<br><br>After these modifications, heap.trc shows the expected information.<br>-JT<br><br><div><hr id="stopSpelling">From: jtm_1986@hotmail.com<br>To: fpc-devel@lists.freepascal.org<br>Date: Mon, 28 Apr 2014 18:26:59 -0500<br>Subject: [fpc-devel] heaptrc: question about missing caller stack<br><br>

<style><!--
.ExternalClass .ecxhmmessage P {
padding:0px;
}

.ExternalClass body.ecxhmmessage {
font-size:12pt;
font-family:Calibri;
}

--></style>
<div dir="ltr">[Sorry for the length and clutter of this post.]<br><br>It is really helpful when tracking down memory leaks to have a call stack that goes all the way to the line where the memory is allocated. Currently, heaptrc does not do this entirely. (At least on my system.)<br><br>I've created a small test program:<br><br>{Test program "HeaptrcTest" ******************************************************}<br>{*********************************************************************************}<br>program HeaptrcTest;<br>uses SysUtils;<br><br>function MyCaptureBacktrace(skipframes,count:sizeint;frames:PCodePointer):sizeint; <br>var<br>  curr_frame,prev_frame: pointer;<br>  curr_addr: codepointer;<br>  i: sizeint;<br>begin<br>  curr_frame:=get_frame;<br>  curr_addr:=get_pc_addr;<br>  prev_frame:=curr_frame;<br>  { *** Leave the following line in to advance past the call to this function *** }<br>  get_caller_stackinfo(curr_frame,curr_addr);<br>  i:=-skipframes;<br>  while (i<count) and (curr_frame>prev_frame) and<br>     (curr_frame<StackTop) do<br>    begin<br>      prev_frame:=curr_frame;<br>  { *** Do not call here so that the current caller stack gets reported *** }<br>//      get_caller_stackinfo(curr_frame,curr_addr); // moved<br>      if (curr_addr=nil) or<br>         (curr_frame=nil) then<br>        break;<br>      if (i>=0) then<br>        frames[i]:=curr_addr;<br>      inc(i);<br>  { *** Moved the line from above to end of loop *** }<br>      get_caller_stackinfo(curr_frame,curr_addr);  // moved here<br>    end;<br>  if i<0 then<br>    result:=0<br>  else<br>    result:=i;<br>end;<br><br><br>procedure TestAllocSecond;<br>var CodeArray: array[0..101] of codepointer;<br>    Frames: Integer;<br>    ii: Integer;<br>begin<br>  AllocMem(1024);<br><br>  WriteLn('');<br>  WriteLn('***** CaptureBacktrace from AllocMem point *****');<br>  Frames := CaptureBacktrace(0, Length(CodeArray), @CodeArray[0]);<br>  for ii := 0 to Frames - 1 do<br>    WriteLn(BackTraceStrFunc(CodeArray[ii]));<br><br>  WriteLn('');<br>  WriteLn('');<br>  WriteLn('***** MyCaptureBacktrace from AllocMem point *****');<br>  Frames := MyCaptureBacktrace(0, Length(CodeArray), @CodeArray[0]);<br>  for ii := 0 to Frames - 1 do<br>    WriteLn(BackTraceStrFunc(CodeArray[ii]));<br>end;<br><br>procedure TestAllocFirst;<br>begin<br>  TestAllocSecond;<br>end;<br><br>begin<br>  if FileExists('heap.trc') then<br>    DeleteFile('heap.trc');<br>  SetHeapTraceOutput('heap.trc');<br><br>  TestAllocFirst;<br>end.<br>{*********************************************************************************}<br>{Output from program "HeaptrcTest" FPC SVN revision 27676 ************************}<br><br><br>When I run this program with FPC from SVN revision 27676 with the options "-MObjFPC -Scghi -O1 -g -gl -gh -vewnhi -Filib\i386-win32 -Fu. -FUlib\i386-win32 -l", I get the following output:<br><br>C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test>heaptrctest<br><br>***** CaptureBacktrace from AllocMem point *****<br>  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br><br><br>***** MyCaptureBacktrace from AllocMem point *****<br>  $004017A2  TESTALLOCSECOND,  line 55 of HeaptrcTest.lpr<br>  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br>  <br>and heap.trc is:<br><br>C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test\HeaptrcTest.exe <br>Heap dump by heaptrc unit<br>63 memory blocks allocated : 3471/3648<br>62 memory blocks freed     : 2447/2624<br>1 unfreed memory blocks : 1024<br>True heap size : 458752 (144 used in System startup)<br>True free heap : 457504<br>Should be : 457520<br>Call trace for block $00312110 size 1024<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br><br>The output from MyCaptureBacktrace is closest to what is needed. The output from heaptrc is of little help.<br>  <br>{*********************************************************************************}<br>{Output from program "HeaptrcTest" FPC modified from SVN revision 27676 **********}<br><br>When I change heaptrc.pp to call CaptureBacktrace with a 0 in the first parameter, and then change CaptureBacktrace to match my edits, I get the following output:<br><br>C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test>heaptrctest<br><br>***** CaptureBacktrace from AllocMem point *****<br>  $0040169D  TESTALLOCSECOND,  line 47 of HeaptrcTest.lpr<br>  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br><br><br>***** MyCaptureBacktrace from AllocMem point *****<br>  $004017A2  TESTALLOCSECOND,  line 55 of HeaptrcTest.lpr<br>  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br>  <br>and heap.trc is:<br><br>C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test\HeaptrcTest.exe <br>Heap dump by heaptrc unit<br>65 memory blocks allocated : 3714/3904<br>64 memory blocks freed     : 2690/2880<br>1 unfreed memory blocks : 1024<br>True heap size : 458752 (144 used in System startup)<br>True free heap : 457504<br>Should be : 457520<br>Call trace for block $01612110 size 1024<br>  $0040DE94<br>  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr<br>  $0040185F  main,  line 70 of HeaptrcTest.lpr<br><br><br>This is closer, but still has some noise in the heaptrc output.<br><br>{*********************************************************************************}<br>{Question*************************************************************************}<br><br>After modifying CaptureBacktrace, why is there a difference in the heap.trc output compared to the CaptureBacktrace called from the program?<br><br>Thanks for your insight,<br>-JT                                       </div>
<br>_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</div>                                        </div></body>
</html>