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@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@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@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@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 _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal