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

J S jtm_1986 at hotmail.com
Sun May 4 00:38:21 CEST 2014


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

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. 

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

After these modifications, heap.trc shows the expected information.
-JT

From: jtm_1986 at hotmail.com
To: fpc-devel at lists.freepascal.org
Date: Mon, 28 Apr 2014 18:26:59 -0500
Subject: [fpc-devel] heaptrc: question about missing caller stack




[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  		 	   		  

_______________________________________________
fpc-devel maillist  -  fpc-devel at lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20140503/b0f96c7a/attachment.html>


More information about the fpc-devel mailing list