2011-05-12 36 views
3

我正在使用JCLDebug(Click Here获取更多信息)在DUnit中显示堆栈跟踪。请参阅下面的堆栈跟踪。JCLDebug堆栈跟踪缺少导致错误的实际代码行

堆栈跟踪显示所有调用功能,调用导致错误的实际功能。 ConvertScriptTestU的第238行调用另一个称为“GetDataLine”的函数(它从堆栈跟踪中丢失),然后然后调用IntToStr(这会引发EConvertError)。为什么堆栈跟踪不包括GetDataLine

该堆栈跟踪的用处不大,因为我仍然需要计算GetDataLine中的哪一行导致EConvertError。

我在这里使用DUnit,但是我看到在DUnit外部使用JclDebug时会发生同样的情况。

[答案]

此行只是添加到您的项目文件:

JCLdebug.JclStackTrackingOptions:=[stStack, stRawMode]; 

原来的 “原始模式”。您可能需要调整一些编译器选项太多(例如“产生堆栈帧”)

[/答案】

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") 
+0

如果你生成栈帧为相同的代码会发生什么。 – 2011-05-12 04:37:31

+0

@Robert我改变了代码生成 - >堆栈帧为'真',但输出是相同的。 – awmross 2011-05-12 04:42:28

回答

7

这可能取决于您编译应用程序的方式。出于调试目的,您应该在编译器代码生成选项中将Stack Frames设置为On,并确保所有需要的单元都重新编译,并且它们的符号可用。否则,编译器可能会选择不为某些函数生成它们。无论如何,手编的纯汇编函数可能没有堆栈帧,IIRC。如果在支持Delphi的版本中内联函数,可能会出现另一个问题。另外,您在JCL调试中设置了哪种堆栈跟踪? IIRC支持标准和“原始”两种方法。

+0

我已经将'代码内联控制'设置为'关闭','优化'为'假','本地符号'为真,'符号参考信息'为'参考'。然后我做了一个'干净'和'建立'。不幸的是没有什么区别。 – awmross 2011-05-12 08:23:18

+2

是的!将堆栈跟踪设置为“原始”给了我完整的堆栈跟踪。我添加了一行“JCLdebug.JclStackTrackingOptions:= [stStack,stRawMode];”到我的DUnit项目文件,现在它工作。 – awmross 2011-05-12 08:57:58

2

这样的事情发生在堆栈跟踪了很多,当错误引起人们的关注。由于没有用于执行堆栈跟踪的官方API,因此跟踪生成器必须一次一个帧地向后穿过堆栈。但是,如果任何中介函数没有设置堆栈帧,或者由于某种原因,它会以奇怪的方式在堆栈中进行操作,那么它可以将跟踪器放到一个循环中。

这在64位Delphi中可能会更可靠,因为Windows强制使用某种类型的堆栈帧,因此如果引发异常,它可以正确地展开堆栈,但对于32位而言,它是某种东西我们必须忍受。

0

使用Delphi的默认register调用约定时,参数可以放入寄存器EAX,EDX和ECX的过程或函数不使用堆栈帧。

如果使用stdcallcdecl调用约定,则调用该例程将始终使用堆栈。
如果你设置了stack frame on{$W+}{$STACKFRAMES ON}德尔福将始终生成堆栈帧,即使他们不需要。

我建议你设置一个条件这个编译器开关定义

{$IFDEF DEBUG} 
    {$W+} 
{$ELSE} 
    {$W-} 
{$ENDIF} 

参见:http://docwiki.embarcadero.com/RADStudio/XE/en/Stack_frames_(Delphi

+0

打开或关闭堆栈帧在这种情况下似乎没有什么区别。 – awmross 2011-05-12 09:00:55

+0

@awmross,并改变调用约定? – Johan 2011-05-12 09:02:07

+0

@awmross,如果你使用的是你没有写的单元,那么你需要使用调试DCU(用于VCL单元),或者尝试通过编辑这些单元的源代码来强制重新编译,并把{$ W +}条件指令in。 – Johan 2011-05-12 09:04:21