私は、大規模なアプリケーションに Delphi 2007 を使用しているチームのメンバーです。他に説明のつかない奇妙なバグが時々あるため、ヒープの破損が疑われます。コンパイラの Rangechecking オプションは配列専用だと思います。アプリケーションによって割り当てられていないメモリ アドレスに書き込みがあった場合に、例外またはログを記録するツールが必要です。
よろしく
EDIT : エラーのタイプは次のとおりです。
エラー: モジュール 'BoatLogisticsAMCAattracsServer.exe' のアドレス 00404E78 でアクセス違反が発生しました。アドレス FFFFFFDD の読み出し
EDIT2:すべての提案をありがとう。残念ながら、解決策はそれよりも深いと思います。ソースを所有しているため、パッチを適用したバージョンの Bold for Delphi を使用しています。おそらく、Bold フレームワークで導入されたいくつかのエラーがあります。はい、JCL によって処理され、メッセージをトレースするコールスタックを含むログがあります。したがって、例外のあるコールスタックは次のようにロックできます。
20091210 16:02:29 (2356) [EXCEPTION] Raised EBold: Failed to derive ServerSession.mayDropSession: Boolean
OCL expression: not active and not idle and timeout and (ApplicationKernel.allinstances->first.CurrentSession <> self)
Error: Access violation at address 00404E78 in module 'BoatLogisticsAMCAttracsServer.exe'. Read of address FFFFFFDD. At Location BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)
Inner Exception Raised EBold: Failed to derive ServerSession.mayDropSession: Boolean
OCL expression: not active and not idle and timeout and (ApplicationKernel.allinstances->first.CurrentSession <> self)
Error: Access violation at address 00404E78 in module 'BoatLogisticsAMCAttracsServer.exe'. Read of address FFFFFFDD. At Location BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)
Inner Exception Call Stack:
[00] System.TObject.InheritsFrom (sys\system.pas:9237)
Call Stack:
[00] BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)
[01] BoldSystem.TBoldMember.DeriveMember (BoldSystem.pas:3846)
[02] BoldSystem.TBoldMemberDeriver.DoDeriveAndSubscribe (BoldSystem.pas:7491)
[03] BoldDeriver.TBoldAbstractDeriver.DeriveAndSubscribe (BoldDeriver.pas:180)
[04] BoldDeriver.TBoldAbstractDeriver.SetDeriverState (BoldDeriver.pas:262)
[05] BoldDeriver.TBoldAbstractDeriver.Derive (BoldDeriver.pas:117)
[06] BoldDeriver.TBoldAbstractDeriver.EnsureCurrent (BoldDeriver.pas:196)
[07] BoldSystem.TBoldMember.EnsureContentsCurrent (BoldSystem.pas:4245)
[08] BoldSystem.TBoldAttribute.EnsureNotNull (BoldSystem.pas:4813)
[09] BoldAttributes.TBABoolean.GetAsBoolean (BoldAttributes.pas:3069)
[10] BusinessClasses.TLogonSession._GetMayDropSession (code\BusinessClasses.pas:31854)
[11] DMAttracsTimers.TAttracsTimerDataModule.RemoveDanglingLogonSessions (code\DMAttracsTimers.pas:237)
[12] DMAttracsTimers.TAttracsTimerDataModule.UpdateServerTimeOnTimerTrig (code\DMAttracsTimers.pas:482)
[13] DMAttracsTimers.TAttracsTimerDataModule.TimerKernelWork (code\DMAttracsTimers.pas:551)
[14] DMAttracsTimers.TAttracsTimerDataModule.AttracsTimerTimer (code\DMAttracsTimers.pas:600)
[15] ExtCtrls.TTimer.Timer (ExtCtrls.pas:2281)
[16] Classes.StdWndProc (common\Classes.pas:11583)
内部例外部分は、例外が再発生した瞬間のコールスタックです。
EDIT3:現在の理論は、仮想メモリテーブル(VMT)が何らかの形で壊れているというものです。これが発生した場合、その兆候はありません。メソッドが呼び出されたときにのみ例外が発生します (アドレス FFFFFFDD でALWAYS、10 進数で -35) が、それでは遅すぎます。エラーの本当の原因がわからない。このようなバグをキャッチする方法のヒントは本当にありがたいです!!! SafeMM で試してみましたが、3 GB フラグを使用してもメモリ消費量が多すぎることが問題です。だから今、私はSOコミュニティに報奨金を与えようとしています:)
EDIT4: 1つのヒントは、ログによると、この前に別の例外がしばしば(または常に)あるということです。たとえば、データベースの楽観的ロックなどです。強制的に例外を発生させようとしましたが、テスト環境では問題なく動作します。
EDIT5:話は続きます... 過去 30 日間のログを検索しました。結果:
- 「アドレス FFFFFFDB の読み出し」 0
- 「アドレス FFFFFFDC の読み出し」 24
- 「アドレス FFFFFFDD の読み取り」 270
- 「アドレス FFFFFFDE の読み出し」 22
- 「アドレス FFFFFFDF の読み出し」 7
- 「アドレス FFFFFFE0 の読み出し」 20
- 「アドレス FFFFFFE1 の読み出し」 0
したがって、現在の理論では、列挙型 (ボールド体にたくさんあります) がポインターを上書きします。上記の異なるアドレスで 5 件ヒットしました。列挙型が 5 つの値を保持し、2 番目の値が最も使用されていることを意味する可能性があります。例外が発生した場合、データベースのロールバックが発生し、Boldobjects が破棄される必要があります。おそらく、すべてが破棄されるわけではなく、列挙型がまだアドレスの場所に書き込むことができる可能性があります。これが本当なら、5 つの値を持つ列挙型の正規表現でコードを検索することは可能でしょうか?
EDIT6:要約すると、問題の解決策はまだありません。コールスタックで少し誤解を招く可能性があることは承知しています。はい、タイマーがありますが、タイマーのない他のコールスタックがあります。そのために残念。しかし、2つの共通点があります。
- アドレス FFFFFFxx の読み取りによる例外。
- コールスタックのトップは System.TObject.InheritsFrom (sys\system.pas:9237) です。
これは、 VilleKが問題を最もよく説明していることを確信させてくれます。また、問題は Bold フレームワークのどこかにあると確信しています。しかし、大きな問題は、このような問題をどのように解決できるかということです。VilleKのような Assert を提案するだけでは十分ではありません。損傷は既に発生しており、その時点でコールスタックはなくなっているからです。したがって、エラーの原因についての私の見解を説明するには、次のようにします。
- どこかでポインターに不適切な値 1 が割り当てられていますが、0、2、3 などになることもあります。
- オブジェクトがそのポインターに割り当てられます。
- オブジェクトの基底クラスにメソッド呼び出しがあります。これにより、メソッド TObject.InheritsForm が呼び出され、アドレス FFFFFFDD に例外が発生します。
これら 3 つのイベントはコード内で一緒に使用できますが、後で使用することもできます。これは最後のメソッド呼び出しにも当てはまると思います。
EDIT7:私たちは Bold Jan Norden の作者と緊密に協力しており、彼は最近、Bold フレームワークの OCL エバリュエーターにバグを発見しました。これが修正されたとき、これらの種類の例外は大幅に減少しましたが、それでも時々発生します。しかし、これがほぼ解決されたことは大きな安堵です。