2009-07-09 3 views
5

私は過去に消えたこの厄介なバグを持っていましたが、かなりの時間後に戻ってきました。FastMM4は "ブロックヘッダが壊れています"と答えています

私は、(TObjectListから派生した)TAsmJobオブジェクトに作成されロードされた2つのTSamオブジェクト(TPersistentから派生したもの)を持っています。

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

私はプログラム全体で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のデータもテキストで表示されます。私が持っている

つの質問:私はエラーがどこにあるか見つけるために小さな断片にプログラムをブレークした場合、エラーがまだ表示されますか?または、この特定の構成でのみ表示することは可能ですか?


への回答、「どのようにTStringGridはAsmJobを破壊することを、あなたは私たちを見ることができるようにAsmJobはTStringGridに割り当てられますでしょうか?」

begin 
    FreeAndNil(AsmJob); 
    inherited 
end; 

答えて

12

このエラーは、コードが内部メモリマネージャの構造を破損していることを意味します。呼び出しスタックは、MMがこれを検出した時点を表します。これは、エラーパスやそれに関連するものではありません。実際のエラーはこの瞬間に発生します。 上記のクラスと関連していてもいなくてもかまいません。

You should try to use "Range check errors" option (don't forget to make Build, not Compile) and FastMM in full debug mode (with CheckHeapForCorruption, CatchUseOfFreedInterfaces и DetectMMOperationsAfterUninstall options enabled)

FullDebugModeScanMemoryPoolBeforeEveryOperationグローバル変数をオンにして、問題が発生した直後にエラーを表示することもできますが、このオプションを選択すると実行が非常に遅くなります。

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

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

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

+0

ありがとうアレクサンダー。私は "ScanMemoryPoolForCorruptions"について何の手がかりも持っていませんでした。私は、FastMM DLLが提供する関数だと思います。私は今それについて検索するつもりです。 – Ampere

+0

これは、標準のFastMM4.pasからの機能です。 FastMMの完全スタンドアロン版です。 Delphiに統合されたFastMMのバージョンには存在しません。 問題のDLLはありません。これは通常のpasファイル内の単なる関数です;) – Alex

+0

悲しいことにリンクが死んでいます。しかし、あなたはhttp://web.archive.org/web/20091007162116/http://blog.eurekalog.com/?p=198でアクセスすることができます。 – EMBarbosa

4

A:

MyGrid = TStringGrid 
    public 
    AsmJob: TAsmJob; 
    end; 

は、どこかTForm.Create(グリッドを保持している形)で、私は

MyGrid.AsmJob=AsmJob; 

と私はMyGridのデストラクタで行いますブロックヘッダーが破損しているとは、通常、何らかの安全でない操作を行うことによって、何かがメモリを上書きしていることを意味します。どのようなタスクでも未加工のポインタやアセンブリコードを使用していますか?また、範囲チェックと境界チェックがオフになっている場合は、それらをオンにして再構築してみてください。彼らはこの種の問題をたくさん捉えることができます。

+0

こんにちは。 ASMはありません。ロー・ポインタ操作はありません。レンジ・チェックは常にONです。 これはまさに私が今日の一日を把握しようとしていることです。その地獄のオブジェクトを上書きすることができる場所です。 – Ampere

+1

これまでに一度このような状況が見られました。最終的に私が使用していた第三者図書館にそれを追跡しました。それは生のポインタでいくつかの操作をしていて、それらのうちのいくつかを不安定にしていました。それはここの場合かもしれませんか? –

+0

それは上書きされているオブジェクトではなく、メモリブロックヘッダーのように見えません。しかし、確かに、デストラクタが実行される前にこのオブジェクトの状態を調べることを可能にするクリーンアップコードにブレークポイントを入れてみてください。デバッガでそれを見て、フィールドが有効であることを確認してください。 (そうでない場合は、アドレスブレークポイントを使用してメモリを上書きするものを見つけることができます) –

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を破壊することを、あなたは私たちを見ることができるように

At runtime, a form creates a TStringGrid and then the AsmJob which creates those two SAM objects (and load some data from disk in each of them). The AsmJob is also assigned to the grid. When the form is destroyed, the Grid takes care of the AsmJob by freeing it, which frees the TSam objects. Here is the problem: the first object is freed withot problems but the second one dies when its inherited method (in Destroy destructor) is called.

私の最初の質問はどのようにAsmJobはTStringGridに割り当てられますないされていることを述べますか?

第二には、なぜそれが2つのオブジェクトを格納するために取得するためにTObjectListをの子孫を作成し、自由に自分で作成し、上記のようにTObjectListを、それらを破壊させるのではなく、それらを解放します。

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

+0

こんにちはRyan。もともと、ObjectListはOwnObj = trueに設定されていましたが、オブジェクトを "手動で"解放して、エラーがどこに表示されるかを確認します。これは、TSamオブジェクトの継承された(破棄された)呼び出しでエラーが表示されることを示しています。 いつでも!手動でTSamオブジェクトを作成して使用する場合(つまり、これらのオブジェクトのマネージャの一種であるTAsmJobがない場合)、すべてがうまく動作します。私には全く誤りはありません。 -------- PS:私はすでに完全なデバッグモードでFastMMを持っています。 – Ampere

2

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

もう1つの方法として、コードをサブクラス化してロギングを追加し、オブジェクトが順次アクセスされているかどうかをチェックすることができます。

関連する問題