[fpc-pascal] missing stacktrace - why?

Bernd prof7bit at googlemail.com
Mon Jul 4 22:57:40 CEST 2011


consider the following code:

program extest;

{$mode objfpc}{$H+}

uses
  Classes, Sysutils;

{$R *.res}

procedure foo;
var
  L : TStringList;
  S : String;
begin
  raise Exception.Create('foo');
  //L := TStringList.Create;
  //s := L.Strings[0];
end;

procedure bar;
begin
  foo;
end;

begin
  try
    bar;
  except
    on E: Exception do begin
      writeln(E.ToString, ': ', E.Message);
      DumpExceptionBackTrace(StdOut);
    end;
  end;
end.

if I compile with -gl and no optimizations and execute this then it
will dump a stack trace to the console:

bernd at t40:~/Desktop/except\ $ ./extest
Exception: foo
  $080480DE  FOO,  line 15 of extest.pas
  $08048148  BAR,  line 22 of extest.pas
  $080481A8  main,  line 27 of extest.pas
bernd at t40:~/Desktop/except\ $

This is exactly what I expect it to do. If I now change the following
lines to intentionally produce an out-of-bounds exception in the empty
TStringList:

  // raise Exception.Create('foo');
  L := TStringList.Create;
  s := L.Strings[0];

then the output in the console looks like this:

bernd at t40:~/Desktop/except\ $ ./extest
EStringListError: List index (0) out of bounds
  $080705B0  TSTRINGLIST__GET,  line 1019 of
/home/bernd/lazsvn/fpc/rtl/objpas/classes/stringl.inc
bernd at t40:~/Desktop/except\ $

The stack trace is much shorter and I don't have the slightest idea why.


If I use the debugger to step into the code it looks like this:

#0 _$CLASSES$_Ll2079(0x80b63ac 'List index (%d) out of bounds', 0,
0xb7ee60a0) at /home/bernd/lazsvn/fpc/rtl/objpas/classes/stringl.inc:408
#1 _$CLASSES$_Ll2413(0, 0x0, 0x0) at
/home/bernd/lazsvn/fpc/rtl/objpas/classes/stringl.inc:1019
#2 FOO at extest.pas:17
#3 BAR at extest.pas:22
#4 main at extest.pas:27

The above is at the moment when execution is at the line starting with
"raise" in the following code in stringl.inc

Procedure TStrings.Error(const Msg: string; Data: Integer);
begin
  Raise EStringListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
end;

I have compiled FPC with OPT="-O3 -OoNoSTACKFRAME -gl" (next thing I
am going to try is no optimization at all). I have learned that O2 or
higher (specifically OoSTACKFRAME) will mess with stack traces and
make them virtually impossible, so I deliberatly compiled everything
with OoNoSTACKFRAME but it did not seem to help here. Failing to turn
off this optimization will also make call-stacks in gdb difficult or
impossible but here it seems GDB is perfectly able to trace the
complete stack right until before the raise statement.

I don't understand the following two things:
- why don't I get a proper stack trace when the exception in TStrings is raised?
- why does it name the functions _$CLASSES$_Ll2079 and
_$CLASSES$_Ll2413 in the gdb call stack and not show the correct
function names but the functions from my own code are properly
spelled?

Is there any possibility to extract the proper and complete!) call
stack at runtime when catching and handling an exception that does not
suffer from these problems?

Or is this just a bug (I am using 2.5.1 latest svn) and I should not worry?

Bernd



More information about the fpc-pascal mailing list