1

我们有一个运行了几年的 Delphi 应用程序,现在突然出现奇怪的访问冲突。我们使用 Eurekalog 来追踪它的来源,这更加奇怪。到目前为止,它们都在对象的 Free 调用中,但在 try except 块中。其中之一甚至在 2 个 try except 块中,当访问冲突发生时,它仍然完全跳出程序并忽略 try 例外,除了 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,而不是客户端。

4

1 回答 1

1

如果此行:ClientCommunication.Free;导致异常。您可以在这里做几件事。

FreeAndNil
将调用替换为AObject.free调用freeandnil(AObject)
如果您只是执行释放,旧指针仍将具有非零引用,并且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 它有一些来自 Delphi 附带 的额外花里胡哨。慢,但也发现了很多你似乎正在遭受的堆损坏错误。

打开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

(*)我认为 Delphi 也有大部分的调试功能,但不是 100% 肯定。无论如何,获得最新(最好的)版本不会有什么坏处。

或者缓冲区溢出
如果你的ClientCommunication对象有一些内部结构,free 会做额外的工作。

想象一下下面的代码:

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旁边。 调用也将覆盖 的数据。 这可能会也可能不会触发 DoWork 中的访问冲突。如果没有,那么错误将很难追踪,因为它会出现在不同且完全不相关的地方。 UnrelatedObject
DoWorkClientCommunication

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

警告
请记住不要将调试版本发送给您的客户。
通过所有调试,您的程序将非常缓慢。

于 2013-10-25T13:30:30.460 回答