4

現在、C++ライブラリの上に構築されたC#(.Net 4.5)WPFアプリケーションをテストしています(マネージド、私はそれを書いていないと思います)。さまざまな(実際的な)理由から、サーバー上で実行されています(VS2012がインストールされています、はい、そうです)。

プログラムは (ライブラリ経由で) カメラに接続し、受信した画像フレームを表示します。

奇妙なのは、バッファオーバーラン(理解できるバッファ オーバーフロー) が発生していることです。そしてガベージコレクション中!

A buffer overrun has occurred in App.exe which has corrupted the program's internal state.

その他の役立つ可能性のあるさまざまな情報:

  • 「スループット」を上げると、処理が早くなります (数分ではなく数秒)
  • VS(デバッグまたはリリース)で実行すると、それがまったく停止します(または、少なくとも、待機する準備ができているよりも長く遅延します)
  • 私のC#にはありませんunsafe。私が行っている唯一の「難解な」ことは、(ライブラリからの)ビットマップを(このBitmapSourceような)に変換することです。
  • ライブラリは x86 用にコンパイルされており、exe も同様です。

コールスタック、毎回同じ:

vcr110_clr0400.dll!__crt_debugger_hook ()   Unknown
clr.dll!___raise_securityfailure () Unknown
clr.dll!___report_gsfailure ()  Unknown
clr.dll!CrawlFrame::SetCurGSCookie(unsigned long *) Unknown
clr.dll!StackFrameIterator::Init(class Thread *,class Frame *,struct _REGDISPLAY *,unsigned int)    Unknown
clr.dll!Thread::StackWalkFramesEx(struct _REGDISPLAY *,enum StackWalkAction (*)(class CrawlFrame *,void *),void *,unsigned int,class Frame *)   Unknown
clr.dll!Thread::StackWalkFrames(enum StackWalkAction (*)(class CrawlFrame *,void *),void *,unsigned int,class Frame *)  Unknown
clr.dll!CNameSpace::GcScanRoots(void (*)(class Object * *,struct ScanContext *,unsigned long),int,int,struct ScanContext *,class GCHeap *)  Unknown
clr.dll!WKS::gc_heap::mark_phase(int,int)   Unknown
clr.dll!WKS::gc_heap::gc1(void) Unknown
clr.dll!WKS::gc_heap::garbage_collect(int)  Unknown
clr.dll!WKS::GCHeap::GarbageCollectGeneration(unsigned int,enum WKS::gc_reason) Unknown
clr.dll!WKS::GCHeap::GarbageCollectTry(int,int,int) Unknown
clr.dll!WKS::GCHeap::GarbageCollect(int,int,int)    Unknown
clr.dll!GCInterface::Collect(int,int)   Unknown
mscorlib.ni.dll!6dcd33e5()  Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for mscorlib.ni.dll]   
mscorlib.ni.dll!6dcd33e5()  Unknown
064afa73()  Unknown
clr.dll!MethodTable::FastBox(void * *)  Unknown
clr.dll!MethodTable::CallFinalizer(class Object *)  Unknown
clr.dll!SVR::CallFinalizer(class Object *)  Unknown
clr.dll!SVR::CallFinalizer(class Object *)  Unknown
clr.dll!SVR::CallFinalizer(class Object *)  Unknown
clr.dll!WKS::GCHeap::FinalizerThreadWorker(void *)  Unknown
clr.dll!Thread::DoExtraWorkForFinalizer(void)   Unknown
clr.dll!Thread::DoExtraWorkForFinalizer(void)   Unknown
clr.dll!Thread::DoExtraWorkForFinalizer(void)   Unknown
clr.dll!WKS::GCHeap::FinalizerThreadStart(void *)   Unknown
clr.dll!Thread::intermediateThreadProc(void *)  Unknown
kernel32.dll!@BaseThreadInitThunk@12 () Unknown
ntdll.dll!___RtlUserThreadStart@8 ()    Unknown
ntdll.dll!__RtlUserThreadStart@8 () Unknown
4

2 に答える 2

4

v2 CLR とは異なり、v4 CLR は Microsoft セキュア CRT 拡張機能を有効にして構築されました。関数の終了時に、「スタックカナリア」が上書きされなかったことを確認します。/GS コンパイラ オプションによって有効になります。

以前のバージョンでプログラムが終了する可能性があったのは、Fatal Execution Engine Exception でした。これは、関数が戻りを試み、戻りアドレスが破損したときに発生したアクセス違反によってトリガーされました。これで、問題がより早く検出されます。さらに確実なのは、その破損したリターン アドレスが誤って有効なコードを指している可能性があることです。その場合に次に何が起こるかは、通常、本当に診断できません。そして悪用可能。

しかし、根本的な原因は同じで、GC ヒープが破損しています。

于 2013-05-08T12:56:03.590 に答える
3

私にはメモリの破損のように見えます。ライブラリは、安全でないメモリや管理されていないメモリ、または固定されたメモリを使用している可能性があります...または、メモリの正しいビットを固定していないか、固定を解除するのが早すぎますか?

はどうかと言うと:

VS(デバッグまたはリリース)で実行すると、それがまったく停止します(または、少なくとも、待機する準備ができているよりも長く遅延します)

これは、デバッガーによって作成されたプロセスが別のヒープを使用するためです (リリース モードで実行している場合でも)。この代替ヒープを使用すると、ランダムなメモリ破損を処理するときにハイゼンバグの既知のソースになります (ただし、この点に関する多くのソースは見つかりませんでした。Raymond Chen のブログのどこかにあると思っていましたが、これしか見つかりませんでした)

編集:参照が見つかりました!MSDNから:

デバッガーが作成するプロセス (生成されたプロセスとも呼ばれます) は、デバッガーが作成しないプロセスとは動作が少し異なります。
標準ヒープ API を使用する代わりに、デバッガーが作成するプロセスは特別なデバッグ ヒープを使用します。_NO_DEBUG_HEAP 環境変数または -hd コマンドライン オプションを使用して、生成されたプロセスがデバッグ ヒープの代わりに標準ヒープを使用するように強制できます。

私の最善の推測は、C++ ライブラリが一部のメモリを破損していることです。GC が来て、ヒープが破損していることを発見し、クラッシュします。または: C++ ライブラリは、イメージのバッファとして使用しているメモリを確保するのを忘れています。GC が来て、メモリを移動します。C++ ライブラリは認識せず、無効になったポインターに書き込み、破損を引き起こします。GC が再び来て、現在破損しているメモリで作業を開始し、クラッシュします。

于 2013-05-08T12:51:38.323 に答える