我在Delphi 2007中编写了应用程序,有时会挂起(甚至不是每周都有应用程序运行24/7)。看起来主线程卡住了。有哪些方法可以找出导致此问题的原因?
应用程序是用Delphi 2007编写的,它使用RemObjects,DBExpress和Firebird,使用COM进行OPC通信。
答案 0 :(得分:11)
使用MadExcept,您可以指定定期检查主线程以仍处理消息(使用变量超时,您将设置为高于最长操作所需的值)。如果主线程挂起,则可以获得堆栈跟踪。
请参阅Main thread freeze checking...
我已经成功使用了它,但只有当挂起在驱动程序中时才会失败(这可能是预期的)。在开始怀疑驱动程序(对于A / D转换卡)之后,我在每个API调用之前和之后添加了跟踪消息,并且能够证明驱动程序是罪魁祸首。请注意,立即将消息写入文件并刷新缓冲区以获取可靠的日志数据非常重要。
我还成功地使用WinDbg附加到没有安装Delphi的系统上挂起的可执行文件。事实证明,这并不总是以相同的顺序获取关键部分。 WinDbg通过检查线程堆栈和关键部分的状态来帮助分析这种情况。
答案 1 :(得分:4)
我为此使用了一个“看门狗”线程,它检查主机是否响应,并制作一个minidump(您可以使用WinDbg加载此转储,使用map2dbg.exe将Delphi .map转换为.dbg)。
FMainformHandle := Application.MainForm.Handle;
Result := SendMessageTimeOut( FMainformHandle, WM_NULL, 0, 0,
SMTO_NORMAL or SMTO_ABORTIFHUNG,
C_TIME_OUT_SECONDS * 1000, //wait 1minute
iRes) <> 0;
if not Result then
begin
hFile := CreateFile(PChar(Result), GENERIC_WRITE, FILE_SHARE_WRITE, nil,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
try
MiniDumpWriteDump(GetCurrentProcess, GetCurrentProcessId, hFile,
aDumpType, nil, nil ,nil);
finally
FileClose(hfile);
end;
end;
但你也可以使用
jclDebug.pas:
JclCreateThreadStackTraceFromID(MainthreadId)
为此(不需要WinDbg等,只有JCL + Delphi .map)
第三个选项是使用我的新sampling profiler,它有一个“进程堆栈查看器”,所以你可以看到正在运行的进程的任何线程的堆栈(之前我使用过SysInternals Process Explorer,但它需要.dbg文件)。它使用.map,TD32,JDBG等(任何Delphi调试信息)进行堆栈跟踪 您可以在应用挂起时使用此功能来调查堆栈。
Windows API(适用于MiniDumpWriteDump):
http://sourceforge.net/projects/jedi-apilib/files/JEDI%20Windows%20API/
WinDbg的:
http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx
Map2Dbg:
http://code.google.com/p/map2dbg/
JEDI JCL:
http://jcl.delphi-jedi.org/
AsmProfiler,采样模式:(仍在开发中!)
http://asmprofiler.googlecode.com/files/AsmSamplingProfiler0.4.zip