[fpc-devel] heaptrc: question about missing caller stack

J S jtm_1986 at hotmail.com
Tue Apr 29 01:26:59 CEST 2014


[Sorry for the length and clutter of this post.]

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.)

I've created a small test program:

{Test program "HeaptrcTest" ******************************************************}
{*********************************************************************************}
program HeaptrcTest;
uses SysUtils;

function MyCaptureBacktrace(skipframes,count:sizeint;frames:PCodePointer):sizeint; 
var
  curr_frame,prev_frame: pointer;
  curr_addr: codepointer;
  i: sizeint;
begin
  curr_frame:=get_frame;
  curr_addr:=get_pc_addr;
  prev_frame:=curr_frame;
  { *** Leave the following line in to advance past the call to this function *** }
  get_caller_stackinfo(curr_frame,curr_addr);
  i:=-skipframes;
  while (i<count) and (curr_frame>prev_frame) and
     (curr_frame<StackTop) do
    begin
      prev_frame:=curr_frame;
  { *** Do not call here so that the current caller stack gets reported *** }
//      get_caller_stackinfo(curr_frame,curr_addr); // moved
      if (curr_addr=nil) or
         (curr_frame=nil) then
        break;
      if (i>=0) then
        frames[i]:=curr_addr;
      inc(i);
  { *** Moved the line from above to end of loop *** }
      get_caller_stackinfo(curr_frame,curr_addr);  // moved here
    end;
  if i<0 then
    result:=0
  else
    result:=i;
end;


procedure TestAllocSecond;
var CodeArray: array[0..101] of codepointer;
    Frames: Integer;
    ii: Integer;
begin
  AllocMem(1024);

  WriteLn('');
  WriteLn('***** CaptureBacktrace from AllocMem point *****');
  Frames := CaptureBacktrace(0, Length(CodeArray), @CodeArray[0]);
  for ii := 0 to Frames - 1 do
    WriteLn(BackTraceStrFunc(CodeArray[ii]));

  WriteLn('');
  WriteLn('');
  WriteLn('***** MyCaptureBacktrace from AllocMem point *****');
  Frames := MyCaptureBacktrace(0, Length(CodeArray), @CodeArray[0]);
  for ii := 0 to Frames - 1 do
    WriteLn(BackTraceStrFunc(CodeArray[ii]));
end;

procedure TestAllocFirst;
begin
  TestAllocSecond;
end;

begin
  if FileExists('heap.trc') then
    DeleteFile('heap.trc');
  SetHeapTraceOutput('heap.trc');

  TestAllocFirst;
end.
{*********************************************************************************}
{Output from program "HeaptrcTest" FPC SVN revision 27676 ************************}


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:

C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test>heaptrctest

***** CaptureBacktrace from AllocMem point *****
  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr
  $0040185F  main,  line 70 of HeaptrcTest.lpr


***** MyCaptureBacktrace from AllocMem point *****
  $004017A2  TESTALLOCSECOND,  line 55 of HeaptrcTest.lpr
  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr
  $0040185F  main,  line 70 of HeaptrcTest.lpr
  
and heap.trc is:

C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test\HeaptrcTest.exe 
Heap dump by heaptrc unit
63 memory blocks allocated : 3471/3648
62 memory blocks freed     : 2447/2624
1 unfreed memory blocks : 1024
True heap size : 458752 (144 used in System startup)
True free heap : 457504
Should be : 457520
Call trace for block $00312110 size 1024
  $0040185F  main,  line 70 of HeaptrcTest.lpr

The output from MyCaptureBacktrace is closest to what is needed. The output from heaptrc is of little help.
  
{*********************************************************************************}
{Output from program "HeaptrcTest" FPC modified from SVN revision 27676 **********}

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:

C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test>heaptrctest

***** CaptureBacktrace from AllocMem point *****
  $0040169D  TESTALLOCSECOND,  line 47 of HeaptrcTest.lpr
  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr
  $0040185F  main,  line 70 of HeaptrcTest.lpr


***** MyCaptureBacktrace from AllocMem point *****
  $004017A2  TESTALLOCSECOND,  line 55 of HeaptrcTest.lpr
  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr
  $0040185F  main,  line 70 of HeaptrcTest.lpr
  
and heap.trc is:

C:\DevelopmentEnvironment\Projects\TempProjects\Heaptrc Test\HeaptrcTest.exe 
Heap dump by heaptrc unit
65 memory blocks allocated : 3714/3904
64 memory blocks freed     : 2690/2880
1 unfreed memory blocks : 1024
True heap size : 458752 (144 used in System startup)
True free heap : 457504
Should be : 457520
Call trace for block $01612110 size 1024
  $0040DE94
  $00401828  TESTALLOCFIRST,  line 62 of HeaptrcTest.lpr
  $0040185F  main,  line 70 of HeaptrcTest.lpr


This is closer, but still has some noise in the heaptrc output.

{*********************************************************************************}
{Question*************************************************************************}

After modifying CaptureBacktrace, why is there a difference in the heap.trc output compared to the CaptureBacktrace called from the program?

Thanks for your insight,
-JT  		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20140428/ccf89929/attachment.html>


More information about the fpc-devel mailing list