1

数年間実行されている Delphi アプリがあり、突然奇妙なアクセス違反が発生します。Eurekalog を使用して、それがどこから来たのかを追跡しましたが、これはさらに奇妙です。これまでのところ、それらはすべてオブジェクトの Free 呼び出しにありますが、try except ブロック内にあります。そのうちの 1 つは 2 つの try except ブロック内にあっても、アクセス違反が発生すると、プログラムから完全に飛び出し、try except を無視します。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 を試して抑制するために最後の try except が後で追加されましたが、これは主にアプリを閉じるときに呼び出されます。でもまだそこから飛び出してくるだけで、全然釣れません。

クライアントではなく、開発者の PC で動作します。

4

1 に答える 1

1

この行の場合:ClientCommunication.Free;例外が発生しています。ここでできることがいくつかあります。

FreeAndNilへの呼び出しを への呼び出し
に置き換えます。 解放するだけでは、古いポインターは非 nil 参照のままであり、解放されたオブジェクトとアクティブなオブジェクトを区別できません。 AObject.freefreeandnil(AObject)
Assigned(AObject)

クローンに注意し
てください 犯す可能性のあるもう 1 つの間違いは、次のようにオブジェクトをクローンしたことです。

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 オプション
最新の FastMM4 を http://sourceforge.net/projects/fastmm/
からダウンロードします 。これには、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% 確実ではありません。いずれにせよ、最新 (最高) のバージョンを入手することは問題ありません。

またはバッファオーバーフローオブジェクトに何らかの内部構造がある場合、 free は余分な作業を行います
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すぐ隣にあると想像してください。 を呼び出すと、のデータも上書きされます。 これにより、DoWork でアクセス違反が発生する場合と発生しない場合があります。そうでない場合、エラーはまったく関係のない別の場所に表示されるため、追跡が非常に困難になります。 UnrelatedObject
DoWorkClientCommunication

アプリケーションで範囲チェックを有効{$R+}にします。

警告デバッグ バージョンをクライアントに出荷
ないように注意してください。
すべてのデバッグを行うと、プログラムは非常に遅くなります。

于 2013-10-25T13:30:30.460 に答える