我有一个应用程序每秒进行一次测量(我在演示模式下运行它并生成随机数据,因此问题与从连接到串行端口的设备读取时无关。)
5或6分钟后它会挂起。
我添加了
try
// entire body of procedure/function goes here
except
on E: Exception do
begin
MessageDlg('Internal coding error in <function name>()',
mtError, [mbOK], 0);
end;
end;
到每个函数(和项目文件中的Application.Run()),但是我没有看到任何消息对话框。知道如何测试这个吗?
更新:我认为这是一个资源问题,无论是RAM还是MySql数据库 - 但其他程序运行正常,并且每次测量只保存5个浮点数和时间戳,所以在这么短的时间后,两者似乎都不太可能。
解决方案:有很多很棒的答案(感谢和+1全能),但我终于通过在IDE中运行并使用Run / Pause看到它是一个不断增加的循环来获得它(如建议的那样)。 p>
再次感谢大家。
答案 0 :(得分:5)
我会尝试以下方法:
附加并单击Pause并查看它的位置,正在运行的线程,正在等待的线程(如果所有线程都存在死锁)。
将主要方法重构为一堆小方法(您可能已经这样做了),然后用虚拟/硬编码值替换小方法。这可能有所帮助,但不一定能识别出错误的阻塞。
使用PerfMon或其他东西观察系统资源消耗(句柄,线程等)。查看内存是否耗尽并开始使用硬盘。
如果您使用套接字,请检查您的读取超时是否设置为无穷大。如果是,则更改为某个值并注意超时。
在.NET中,可以启用所有异常的处理,这意味着在代码处理之前(如在catch语句中),IDE会在异常点处中断。如果可能的话,在Delphi中启用它,看看你是否正在使用它。
答案 1 :(得分:5)
使用调试程序查看应用程序在挂起时正在执行的操作。
在调试器下运行程序。让它一直运行直到它挂起。当它挂起时,切换到调试器并选择“Debug:Break All”(或等效)以使调试器冻结所有线程并控制进程。
现在打开调试器中的Threads视图,检查程序中每个线程的堆栈跟踪。显然,从主线程开始。请务必回顾几次调用的调用堆栈,看看是否识别出任何代码。如果找到位于循环中间的堆栈跟踪,请检查局部变量以查看循环控制变量是否以某种方式滑过退出条件并使您进入无限循环。
如果您的堆栈跟踪指示每个线程都被阻塞等待某个外部事件,您可能有一个线程死锁 - 线程A获取锁定A,然后尝试获取锁定B,而线程B持有锁定B并尝试采取锁A.如果你没有在你的程序中使用线程,这种可能性较小,但仍然需要注意它。
如果在查看线程的堆栈跟踪后没有奇怪的事情跳出来,让程序运行几秒钟,然后再用调试器再次进入它并再看一遍。查看堆栈跟踪中的不同之处。
这应该可以帮助您缩小至少涉及哪些代码体的范围。
答案 2 :(得分:1)
如果在添加异常处理程序之前没有看到异常,则不会生成任何要查看的MessageDlgs。
如果程序挂起(而不是被异常爆炸)你可能会出现循环问题,或者你可能有一些永远不会完成的阻塞调用。将日志消息写入窗口或文件(您可以使用OutputDebugStr)将问题隔离到代码的一部分 - 至少是一个函数的主体。您可能会立即看到问题。如果没有,您可以使用OutputDebugStr,断点和跟踪逐行了解该部分代码中发生的情况。
答案 3 :(得分:1)
首先:尝试在Delphi IDE中调试它。
第二:如果你不能这样做(在客户PC上),试试我的(开源)采样分析器的“Process Stack Viewer”:
http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer
(您需要一些调试信息:.map或.jdbg文件)
然后查看你的线程堆栈(可能是主线程/第一线程)。您可以在此处发布堆栈跟踪(如果找不到问题)。
答案 4 :(得分:0)