1

投稿が長すぎて申し訳ありませんが、誰かが少なくとも太字のタイトルを読んで、正しい方向に向けてくれれば幸いです. 私はこの問題を数日間抱えていますが、ネット上で答えを見つけることができませんでした. これらは私がこれまでに発見したことです。

1.「アクセス違反」の例外により、マネージド アプリケーションがクラッシュする

私の C# WinForms アプリは、Windows フォーム TabControl で TabPage を選択した瞬間に、「アクセス違反」例外 (「保護されたメモリの読み取りまたは書き込みを試みました」) で終了することがあります。System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)スタック トレース (Application.Run の周りの try/catch) から、内部で呼び出された で例外が発生していることがわかりますUnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

-- メッセージ: 保護されたメモリを読み書きしようとしました。
   これは多くの場合、他のメモリが破損していることを示しています。
-  スタックトレース:
   System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG& メッセージ) で
   System.Windows.Forms.Application.ComponentManager で
      .System.Windows.Forms.UnsafeNativeMethods
      .IMsoComponentManager.FPushMessageLoop
      (Int32 dwComponentID、Int32 理由、Int32 pvLoopData)
   System.Windows.Forms.Application.ThreadContext で
      .RunMessageLoopInner(Int32 理由、ApplicationContext コンテキスト)
   System.Windows.Forms.Application.ThreadContext で
      .RunMessageLoop(Int32 理由、ApplicationContext コンテキスト)
   System.Windows.Forms.Application.Run (ApplicationContext コンテキスト) で
   MyApp.Program.Main() で

2. 障害モジュールは COM オブジェクトのようです (ChartFX Client Server 6.2)

WinDbg (SoS をロード) を使用して、ChartFX.ClientServer.Core.dll (使用している COM チャート コンポーネント) 内のアンマネージ側でそれをキャッチしました。

(ca84.c98c): アクセス違反 - コード c0000005 (最初のチャンス)
初回例外は、例外処理の前に報告されます。
この例外は予期され、処理される場合があります。
eax=00000000 ebx=06e67c38 ecx=06e67c38 edx=000018c6 esi=06e7df30 edi=317a9e80
eip=31666110 esp=0015e040 ebp=0015e08c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
ChartFX_ClientServer_Core!Ordinal5507+0x97b7:
31666110 8a404d mov al,byte ptr [eax+4Dh] ds:0023:0000004d=??

[編集:] また、管理されていないスタックの詳細を WinDbg から取得できませんでした (「スタック アンワインド情報が利用できません」と表示されました):

0:000>kP
ChildEBP RetAddr  
警告: スタック アンワインド情報は利用できません。次のフレームは間違っている可能性があります。
0015e08c 3166288b ChartFX_ClientServer_Core!Ordinal5507+0x97b7
0015e394 3165a921 ChartFX_ClientServer_Core!Ordinal5507+0x5f32
0015e480 31678685 ChartFX_ClientServer_Core!Ordinal5496+0x26a
0015e568 3167bef4 ChartFX_ClientServer_Core!Ordinal5492+0x975
0015e668 316a356b ChartFX_ClientServer_Core!Ordinal5492+0x41e4
0015e77c 31709496 ChartFX_ClientServer_Core!Ordinal443+0x5745
0015e7d0 31707f70 ChartFX_ClientServer_Core!Ordinal2584+0x3cdc
0015e7f8 3170817d ChartFX_ClientServer_Core!Ordinal2584+0x27b6
0015e81c 3162fd76 ChartFX_ClientServer_Core!Ordinal2584+0x29c3
0015e86c 7719f8d2 ChartFX_ClientServer_Core!Ordinal899+0x6b6
0015e898 7719f794 USER32!GetMessageW+0x93
0015e910 771a06f6 USER32!GetWindowLongW+0x115
0015e940 771a069c USER32!CallWindowProcW+0x75
0015e960 747fcef4 USER32!CallWindowProcW+0x1b
0015e97c 747fd073 comctl32!Ordinal377+0x5c
0015e9e0 747fd027 comctl32!DefSubclassProc+0x92
0015ea04 747fd4e6 comctl32!DefSubclassProc+0x46
0015ea20 747fd073 comctl32!DefSubclassProc+0x505
0015ea84 747fd118 comctl32!DefSubclassProc+0x92
0015eae4 7719f8d2 comctl32!DefSubclassProc+0x137

3. バグの再現は容易ではありません (ただし、通常は 5 分以内に発生する可能性があります)。

複数の TabPages に複数の Chart インスタンスがあり、これは通常、タブを切り替えているときに発生します。問題が発生する前にタブを数分間切り替える以外に、問題を再現する方法がまだわかりません。そのため、ソース管理を使用して、この問題が発生していないビルドを確実に見つけることができません。VS デザイナーによって自動的に作成されたマネージ AxChart ラッパー クラス (AxHost から派生) を介してグラフにアクセスしています。

4. 次のステップは何ですか?

実際の原因を見つけるために私がすべき次のステップを誰かが教えてくれたら、とても感謝しています. 実験 (コードを削除して戻す) はあまり効果がありません。なぜなら、それを再現する方法がわからないためです。そのため、バグがまだそこにあることを自分自身に納得させるためだけに、反復ごとに多大な時間がかかります。

「コンパイラの最適化を切り替える」などの提案がよくあることがわかりましたが、例外は決定論的にスローされないため、単純に一部のバイトを再配置したくなく、返されないことを望みます。

4

3 に答える 3

2

コード全体に多くのログ トレースを追加することで、Chart のプロパティの 1 つが Double.NaN になる場合があることに気付きました。それを取得した後、次のチャートの再描画中にアプリが常にクラッシュしました。Chart の PrePaint イベントと PostPaint イベントを処理することで (幸いなことに、これらのイベントがあります)、これら 2 つのイベントの間にクラッシュが発生することを確認しました。

特に、初めて描画される前にチャートのズームを設定した場合にのみ発生します(前回の更新以降初めて)。私は別の方法でそれを行うことができましたが、それ以来クラッシュしていません。

実際にクラッシュする前に正確に検出できない内部の問題であることは明らかであり、この方法でそれを隠しているだけかもしれないので、私はこの「解決策」にあまり満足していません。しかし、そうしないと時間がかかりすぎるので、今はそのままにしておく必要があります。

[アップデート]

バグの再現に成功

実際に描画される前にいくつかのグラフのプロパティを 2 回設定し、アプリケーションがすぐにクラッシュする簡単なテスト アプリを作成しました。Software FX にバグを報告しましたが、回答がありません。これは、このコントロールで発生した最初の厄介なバグではありませんが、次のリリースではマネージド (.Net) バージョンに切り替えているため、少なくとも Reflector を使用してこれらのバグを解決する方法を見つけます。

とにかくみんなありがとう!

于 2009-03-19T13:29:26.803 に答える
1

これは、スレッドの安全性の問題によく似ています。
コントロールのドキュメントを読むことから始めて、特にスレッドセーフについての言及を探すことをお勧めします。COM コンポーネントで通常使用されるスレッド モデルは、(些細な) .NET の使用とは異なり、多くの場合互換性がありません。

于 2009-03-15T21:16:15.083 に答える
0

しばらく前にこれらの1つを持っていました。適切なケースは、PInvoke 呼び出しでした: OpenPrinter(string port);

私たちの問題は、マネージ コードが "LPT1:" を送信したが、アンマネージ コードが byte[1024] 配列を宣言し、文字列のアドレスから 1024 バイト先を読み取ったことでした。これにより、割り当てられた文字列 ("LPT1:") の境界外が読み取られ、アプリケーションに割り当てられていないメモリに迷い込むことがあり、その結果、この断続的な AccessViolationException が発生していました。

OpenPrinter(int length, string port) の呼び出しを変更して、アンマネージ コードが正しい長さのバイト配列を宣言できるようにすることで、これを修正しました。

ctacke によるこの投稿には、この問題の原因を突き止めるためのヒントも含まれています。

于 2009-03-15T17:08:45.443 に答える