2013-10-25 30 views
1

我们有一个已经运行了几年的Delphi应用程序,现在突然间我们得到了奇怪的访问违规。我们使用Eurekalog来追踪它的来源,这更奇怪。他们到目前为止都是免费调用一个对象,但在一个try块内部。其中一人甚至在2次尝试以外的块中仍然发生访问冲突时,它完全跳出程序并忽略尝试除外,除了EurekaLog在最后捕获它外,没有其他任何内容。真的很困惑,为什么这会突然发生(这两个实例都是旧代码,多年来一直没有被触及,而其他代码更改与它无关)。无法捕获访问冲突

代码的一个例子是

 try 
    if Assigned(ClientCommunication) then begin 
     if ClientCommunication.isConnected then begin 
     if ClientCommunication.closeServerConnection then begin 
      try 
      ClientCommunication.Free; 
      ClientCommunication := nil; 
      Except 
      on e:Exception do begin 
      ClientCommunication := nil; //suppress weird AV error.. get read for new object 
      end 
      end; 

现在最后一次尝试,除了后来加入,试图抑制AV,因为我们只是想清除如果需要重新启动的对象,但是这主要是调用时关闭应用程序。但它只是跳出来,我根本无法捕捉它。

它适用于我们的开发人员PC而不是客户端。

+3

闻起来像堆腐败。解决方案将涉及调试。只有你可以做到这一点。 –

+0

_Heap corruption_很可能是这种情况,但我可以想象'.closeServerConnection()'方法会破坏'ClientCommunication'对象的父对象(通过回调或某些指针杂技),因此任何尝试访问它的操作都可能很容易导致到AV错误。无论哪种情况,您都可以尝试通过向“ClientCommunication”及其父项添加监视来调试问题,然后逐行执行代码并查看指针已释放的位置。 **错误显然不在上面显示的代码中** – mg30rg

+0

我做了这种类型的调试,问题是父母实际上在close内部的任何地方都没有被释放。它只是将关闭命令发送到服务器并关闭连接。这就是为什么它很奇怪。但是,如果堆腐败真的很奇怪。看看我能做些什么,现在添加FastMM4来试试看看它是否能够帮助解决问题。 – Johannes

回答

1

如果该行:ClientCommunication.Free;正在引发异常。 你可以在这里做几件事。

FreeAndNil
通过调用freeandnil(AObject)替换调用AObject.free
如果你只是免费的,旧的指针仍然有一个非零引用,并且Assigned(AObject)将不能分辨释放和活动的对象。

谨防克隆
你可能犯下的另一个错误是,你喜欢克隆对象这样:

Object1:= TObject1.Create; 
//.... lots of code 
Object2:= Object1; 
//.... lots of code 
FreeAndNil(Object2); <<-- freeing the clone-reference is a mistake 
//.... lots of code 
Object1.Free; <<-- exception: it's already freed 

FastMM4选项
http://sourceforge.net/projects/fastmm/
它下载最新的FastMM4 (*)
那些哨子是额外的诊断模式,使哟你的程序死了很慢,但也发现了很多你似乎正在遭受的堆腐败错误。

打开defines.inc并改变这一点:

{$ifdef DEBUG} 
    {.$define EnableMemoryLeakReporting} 
    {.$define FullDebugMode} 
    {.$define RawStackTraces} 
{$endif DEBUG} 

进入这个

{$ifdef DEBUG} 
    {$define EnableMemoryLeakReporting} 
    {$define FullDebugMode} 
    {$define RawStackTraces} 
    {$define CatchUseOfFreedInterfaces} <<-- very useful 
    {$define LogMemoryLeakDetailToFile} 
    {$define LogErrorsToFile} 
    {$define CheckHeapForCorruption} <<-- :-) 
{$endif} 

有一个很好的文章在这里:http://wiert.me/2009/07/29/delphi-fastmm-using-fastmm4-for-debugging-your-memory-allocations-part-1-introduction/
如果你不喜欢摆弄的INC文件,有一个小工具可以为你做:http://jedqc.blogspot.com/2007/07/new-fastmm4-options-interface.html

(*)我认为德尔福的一个也有大部分的调试工具,但不是100%肯定的。无论如何不能伤害到获得最新(最大)的版本。

或缓冲区溢出时
如果您ClientCommunication对象有自由意志,做一些额外的工作的一些内部结构。

想象一下下面的代码:

TUnrelatedObject = class 
    buffer: array[0..99] of integer; 
    procedure DoWork; 
end; 

TUnrelatedObject.DoWork; 
var 
    i: integer; 
begin 
    for i:= 0 to 100 do buffer[i]:= maxint; <<-- buffer overrun 
end; 

试想一下,ClientCommunication毗邻UnrelatedObject堆中。
DoWork的呼叫也会覆盖ClientCommunication的数据。
这可能会或可能不会触发DoWork中的访问冲突。如果没有,那么错误将很难追查,因为它会出现在不同的和完全无关的地方。

在您的应用程序中启用范围检查{$R+}

警告
记住船调试版本给您的客户。
所有的调试程序都会死机。

+0

谢谢大家,这确实有助于很多。斯蒂尔正在研究它,但我相信,在所有这些信息中,我们肯定会找到造成我们问题的具体位置。感谢您花时间和精力来解答这个问题。 – Johannes

+0

只想说谢谢。这些设置帮助了很多,并且随着更多的调试信息和日志记录的发布,我最终发现指针存在问题,并且它似乎是造成这些难以理解的错误的原因。现在一切再次运行良好。谢谢。 – Johannes