Reputation: 3839
I am displaying a stack trace in DUnit using JCLDebug (Click Here for more info). See the stack trace below.
The stack trace shows all calls up to the function that calls the actual function that causes the error. Line 238 of ConvertScriptTestU calls another function called "GetDataLine" (which is missing from the stack trace) that then calls IntToStr (which raises EConvertError). Why does the stack trace not include GetDataLine ?
This stack trace is a lot less useful as I still have to work out which line in GetDataLine is causing the EConvertError.
I am using DUnit here but I have seen the same thing happen when using JclDebug outside DUnit.
[THE ANSWER]
Just add this line to your project file:
JCLdebug.JclStackTrackingOptions:=[stStack, stRawMode];
It turns on "Raw Mode". You might need to tweak some compiler options too (e.g. 'generate stack frames')
[/THE ANSWER]
TestConversion: EConvertError
at SysUtils:0 SysUtils.ConvertErrorFmt$00414A7E
'''' is not a valid integer value
StackTrace
[00414A79]{ConvertDataTests.exe} SysUtils.ConvertErrorFmt
[007E2699]{ConvertDataTests.exe} ConvertScriptTestU.ConvertDataTest.WriteDataToFile (Line 238, "ConvertDataTestU.pas")
[007E2198]{ConvertDataTests.exe} ConvertScriptTestU.ConvertDataTest.TestConversion (Line 164, "ConvertDataTestU.pas")
[0053C66E]{ConvertDataTests.exe} TestFramework.TTestCase.RunTest (Line 2380, "TestFrameWork.pas")
[00537DBA]{ConvertDataTests.exe} TestFramework.TTestResult.RunTestRun (Line 1199, "TestFrameWork.pas")
[00538078]{ConvertDataTests.exe} TestFramework.TTestResult.Run (Line 1275, "TestFrameWork.pas")
[0053963A]{ConvertDataTests.exe} TestFramework.TAbstractTest.RunWithFixture (Line 1723, "TestFrameWork.pas")
[0053C4DD]{ConvertDataTests.exe} TestFramework.TTestCase.RunWithFixture (Line 2363, "TestFrameWork.pas")
Upvotes: 3
Views: 3399
Reputation: 76557
Procedures or functions where the arguments can fit in the registers EAX, EDX and ECX, do not use a stack frame when using Delphi's default register
calling convention.
If you use the stdcall
or cdecl
calling conventions, calling that routine will always use the stack.
If you set stack frame on
{$W+}
or {$STACKFRAMES ON}
Delphi will always generate stack frames, even when they're not needed.
I recommend you set this compiler switch in a conditional define
{$IFDEF DEBUG}
{$W+}
{$ELSE}
{$W-}
{$ENDIF}
See: http://docwiki.embarcadero.com/RADStudio/XE/en/Stack_frames_(Delphi)
Upvotes: 0
Reputation:
It could depend on how you compiled the application. For debugging purposes, you should set Stack Frames to On in compiler code generation options, and ensure all needed units are recompiled, and their symbols are available. Otherwise the compiler may choose not to generate them for some functions. Hand coded pure assembler functions may not have stack frames anyway, IIRC. Another issue could arise if the function is inlined in Delphi releases that supports that. Also, which kind of stack trace did you set up in JCL debug? IIRC it supports two methods, standard and "raw".
Upvotes: 7
Reputation: 84550
This sort of thing happens to stack traces a lot when errors get raised. Since there's no official API for doing stack traces, the trace generator has to pick its way backwards through the stack, one frame at a time. But if any of the intervening functions doesn't set up a stack frame, or if for some reason it does something that plays around with the stack in strange ways, then it can throw the tracer for a loop.
This will probably be a lot more reliable in 64-bit Delphi, because Windows mandates a certain style of stack frames so that it can unwind the stack properly if an exception gets raised, but for 32-bit it's something that we just have to live with.
Upvotes: 2