6

過去に消えたこの厄介なバグがありましたが、かなり時間が経ってから戻ってきました。

2つのTSamオブジェクト(TPersistentから派生)を作成し、TAsmJobオブジェクト(TObjectListから派生)にロードしました。

実行時に、フォームはTStringGridを作成し、次にAsmJobを作成してこれら2つのSAMオブジェクトを作成します(そして、それぞれのディスクからデータをロードします)。AsmJobもグリッドに割り当てられます。フォームが破棄されると、グリッドはAsmJobを解放することで処理し、TSamオブジェクトを解放します。問題は次のとおりです。最初のオブジェクトは問題なく解放されますが、継承されたメソッド(Destroy destructor内)が呼び出されると、2番目のオブジェクトは停止します。

プログラム全体でFreeAndNilを使用して、オブジェクトを解放します。TSamオブジェクトはNILではありません!!!!! したがって、これはオブジェクトを解放する最初の試みです。オブジェクト内のデータでさえ一貫しています。

プログラムのバックボーンは次のようになります。

**Create:**

Form -> StringGrid
     -> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;


**Free:**

Form -> StringGrid -> AsmJob -> Sam1, Sam2

オブジェクトがリリースされた後、どこでオブジェクトをダブルフリーまたは上書きしようとしているのか、本当にわかりません。


編集:

私が得たエラーのいくつか:

  • FastMMは、フリーブロックスキャン操作中にエラーを検出しました。FastMMは、ブロックが解放された後に変更されたことを検出しました。

  • FastMMは、フリーブロックスキャン操作中にエラーを検出しました。ブロックヘッダーが破損しています。

詳細:

The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is: 
402E77 [System][@FreeMem] 
4068DC [System][@DynArrayClear] 
405E2D [System][@FinalizeArray] 
405D31 [System][@FinalizeRecord] 
40432F [System][TObject.CleanupInstance] 
404272 [System][TObject.FreeInstance] 
404641 [System][@ClassDestroy] 
4D313E [UnitSam.pas][TSam.Destroy][297] 
4042BF [System][TObject.Free] 
4149ED [SysUtils][FreeAndNil] 
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180]  

「範囲チェック」を含め、IDEですべての「デバッグ」オプションを有効にしています。また、FastMM4はスーパーアグレッシブデバッグモードに設定されています。FastMMがなくても、デバッガーの外でも、プログラムは問題なく実行されますが、バグがなくなったわけではありません。FastMMをインストールするまで、実際には(おそらく)1年以上機能していました。


編集:

みなさん、ありがとうございました。いいえ、私は少し良い方向に進んでいると感じています。

プログラムの構造はもっと複雑です。元の投稿を小さく保つためにバックボーンのみを提供しました。しかし、一体、それはすでに大きくなっています:)したがって、これらのTSamオブジェクトは、ディスクからデータをロードするために使用されます。各オブジェクトに1つのファイル。彼らはまた、いくつかの処理とデータ検証を行っています。これらのTSamのそれぞれについて、TSamオブジェクトに含まれるデータを画面に(グラフィカルに)表示するグラフィカルオブジェクトもあります。TStringGridの各行には、TSamのデータも表示されますが、テキストで表示されます。

私が持っている1つの質問:エラーがどこにあるかを見つけるためにプログラムを細かく分割しても、エラーはまだ表示されますか?または、この特定の構成でのみ表示することは可能ですか?


「TStringGridがAsmJobを破棄するように、AsmJobはどのようにTStringGridに割り当てられますか?」に対する回答。

MyGrid = TStringGrid
  public 
    AsmJob: TAsmJob; 
  end; 

次に、TForm.Create(グリッドを保持するフォーム)のどこかで、

MyGrid.AsmJob=AsmJob; 

MyGridのデストラクタでは、次のようにします。

begin 
  FreeAndNil(AsmJob); 
  inherited 
end;
4

4 に答える 4

14

このエラーは、コードが内部メモリマネージャの構造を破壊したことを意味します。MMがこれを検出したとき、コールスタックはポイントを表します。これはエラーパスやそれに関連するものではありません。実際のエラーは、この瞬間の前に発生します。言及されたクラスに関連している場合と関連していない場合があります。

「範囲チェックエラー」オプション(コンパイルではなくビルドを作成することを忘れないでください)とFastMMを完全デバッグモード(CheckHeapForCorruption、CatchUseOfFreedInterfacesおよびDetectMMOperationsAfterUninstallオプションが有効になっている)で使用してみてください

FullDebugModeScanMemoryPoolBeforeEveryOperationグローバル変数をオンにして、問題が発生した直後にエラーを取得することもできますが、このオプションを使用すると、実行速度が大幅に低下します。

おそらく最良の選択は、ScanMemoryPoolForCorruptionsを定期的に呼び出すことです。一箇所で呼んでください。エラーが発生しましたか?早く呼んでください。それでもエラーが発生しましたか?もう一度早く電話してください。エラーはありませんか?あなたの問題はそれらの最後の呼び出しの間のどこかにあります。これで、FullDebugModeScanMemoryPoolBeforeEveryOperation変数を使用して、正確な場所を取得できます。このコードの領域でのみオンにし、直後にオフにします。

非常によく似たエラーがあります:「FastMMは、ブロックが解放された後に変更されたことを検出しました」。この場合、コードは内部構造ではなく、まったく使用されていない他のメモリ(「空きメモリ」)を変更します。

ところで、あなたのエラーはダブルフリーではありません!これがダブルフリーコールの場合、FastMMは明示的に次のように通知します(未使用または存在しないメモリブロックを解放しようとしているため、簡単に検出できます)。未割り当てのブロック」。

于 2009-07-10T08:25:33.803 に答える
4

ブロックヘッダーが破損しているということは、通常、何らかの危険な操作を実行することによって、何かがメモリを上書きしていることを意味します。いずれかのタスクで生のポインターまたはアセンブリコードを使用していますか?また、範囲チェックと境界チェックをオフにしている場合は、それらをオンにして再構築してみてください。彼らはこの種の問題の多くを捕まえるのを助けることができます。

于 2009-07-09T20:57:29.170 に答える
2

オブジェクトが解放されているときにオブジェクトが書き込まれているコードのどこかに論理的な競合がある可能性があります。NULLチェックおよびその他のIPCメカニズム(ロックリストなど)を追加して、そうでないことを確認します。

もう1つのオプションは、コードをサブクラス化してログを追加し、オブジェクトが順番にアクセスされているかどうかを確認することです。

于 2013-03-08T19:30:14.607 に答える
1

あなたのコードが見えないので、いくつか質問します。

次のコードが与えられます:

procedure TForm1.FormCreate(Sender: TObject);
var
   wObjLst : TObjectList;
begin
   wObjLst := TObjectList.Create;
   try
      wObjlst.OwnsObjects := true;
      wObjlst.Add(TPersistent.Create);
      wObjlst.Add(TPersistent.Create);
   finally
      freeandnil(wObjlst);
   end;
end;

これはエラーなしで機能します。

あなたはそれを述べます

実行時に、フォームはTStringGridを作成し、次にAsmJobを作成してこれら2つのSAMオブジェクトを作成します(そして、それぞれのディスクからデータをロードします)。AsmJobもグリッドに割り当てられます。フォームが破棄されると、グリッドはAsmJobを解放することで処理し、TSamオブジェクトを解放します。問題は次のとおりです。最初のオブジェクトは問題なく解放されますが、継承されたメソッド(Destroy destructor内)が呼び出されると、2番目のオブジェクトは停止します。

私の最初の質問は、TStringGridがAsmJobを破棄するように、AsmJobがTStringGridにどのように割り当てられるかです。

次に、TObjectListの子孫を作成して、2つのオブジェクトを格納し、上記のように自分で作成してTObjectListに破棄させるのではなく、それらを解放します。

もう1つ試すことは、fastmm.sourceforge.netから完全なFastMM4パッケージをダウンロードして インストールし、fulldebug dllを使用して、失敗しているオブジェクトを正確に追跡することです。あなたと私は、それがSAMオブジェクトの1つであり、そうでない場合もあると想定しています。

于 2009-07-09T22:01:50.290 に答える