3

Visual C++ からリリース モードでアプリケーションを実行すると、次の例外が発生します。

未処理の例外: System.AccessViolationException: 保護されたメモリの読み取りまたは書き込みを試みました。これは多くの場合、他のメモリが破損していることを示しています。_cexit() で .LanguageSupport._UninitializeDefaultDomain(Void * cookie) で .LanguageSupport.UninitializeDefaultDomain() で .LanguageSupport.DomainUnload(オブジェクト ソース、Eve ntArgs 引数) で .ModuleUninitializer.SingletonDomainUnload(オブジェクト ソース、EventArgs 引数) で

これは、デバッグ モードでは発生しません。最初は、自宅のコンピューターでこの例外が発生しましたが、職場のコンピューターでは発生しませんでした。仕事用のコンピューターで開発を続けていたときに、ぶつかってしまいました。

また、3 つの const std::string 変数を追加すると、例外がスローされることがわかりました。私が削除した場合、すべてがうまくいきました。

別の情報: リリース モードでコンパイラの最適化をすべてオフにすると、例外がなくなることがわかりました。

何か怪しいことが起こっている。これを追跡する方法についてのアイデアはありますか?

助けてくれてありがとう、ジョー

4

7 に答える 7

3

ジョー、メモリ リークがあります。

削除されたメモリを使用しようとしている可能性があります。

メモリ リークの一般的な原因とその特定方法については、この記事を参照してください。それ以外の場合は、「C++ メモリ プロファイラ」 + お使いのコンパイラ/プラットフォームを検索してください。お使いのコンパイラとプラットフォームに適したメモリ プロファイラへのリンクが表示されます。これらは追跡に役立ちます。プログラムの実行時にメモリがどのように使用されるかを監視して、メモリ リークを減らします。

お役に立てれば。

編集

それを追跡する方法は?これは私の頭の中から外れています。他にもっと良いアドバイスがあるかもしれません。. .

コードがクラッシュする場所を見つけます。それは、ポインターの内容にアクセスするとき (またはポインターを削除するとき) です。問題は、そのポインターが a) 割り当てられていない b) 既に削除されていることです。そのタイプのポインターへのすべての参照を確認します。それらはコピー ctors/代入演算子で使用されていますか?

もしそうなら、その内容はコピーされていますか、それともポインタだけですか? ポインタだけの場合、それを含むクラスはポインタを削除しようとしていますか? その場合、最初に終了したクラスは成功し、2 番目のクラスはアクセス違反をスローします。

copy ctors と operator= を明示的にコーディングしない場合は、それらを非表示にする必要があります (プライベート プロトタイプを宣言しますが、実装しないでください)。これにより、コンパイラはデフォルトの実装を生成できなくなります。

それらを非表示にすると、使用されているすべての場所でコンパイラエラーが発生します。これらをクリーンアップできるか、各クラスにコピー ctor と operator= を実装する必要がある可能性があります。

私は明日から 2 週間休暇を取ります。これについて質問がある場合は、今日直接メールしてください (私の SO ユーザー ページのリンクをたどってください)。

于 2009-07-02T15:18:05.740 に答える
2

コード内でデバッグ用に #define されたコードはありますか?

すなわち

#ifndef _DEBUG
   //release only code such as liscensing code
#endif

それが問題を引き起こしている可能性のあることの1つであり、私も以前に遭遇しました.

もう 1 つの可能性は、VS の問題 (または使用している IDE) です。開発環境ではなくリリース .exe を直接実行してみて、同じ問題が引き続き発生するかどうかを確認してください。

于 2009-07-02T15:14:10.227 に答える
1

いくつかの可能性:

ローカル配列の終わりを過ぎて読み書きしていると思います。デバッグ ビルドでは、メモリが厳密に割り当てられていないため、これが機能する場合があります。リリース ビルドでは、配列のすぐ隣に何が割り当てられているかによって、これが問題を引き起こす可能性が高くなります。

別の可能性は、どこかに初期化されていないポインターがあることです。VC デフォルトは、デバッグ モードでローカル変数を初期化しますが、リリース モードでは初期化しません。したがって、次のようなコード:

int* p;
if (p != NULL) { /* do something */ }

通常、リリース モードでは失敗します。

于 2009-07-02T15:52:44.760 に答える
1

いわば「怒って」C++ を使用してからしばらく経ちます。そのため、以下で説明する内容の一部 (または実際にはすべて) は古くなっている可能性があります。

マネージ C++ を使用していますか? そうでない場合は、初期化されていないポインターのように聞こえます。以前はすべてのポインターがデバッグで null になっていましたが、この動作をオフにすることについて何か思い出しましたが、今は完全な詳細を思い出せません。

文字列が変数をオーバーランしていませんか? std::string ではありそうにありませんが、削除する価値があります。

于 2009-07-02T15:16:40.517 に答える
0

このエラー メッセージは、メモリに問題があることを強く示唆しており、メモリを上書きしている可能性があります。これらを見つけるのは難しいですが、「ビジュアル C++ メモリ破損ツール」をグーグルで検索すると、いくつかの可能な解決策を見つけることができます。

メモリの破損についての問題は、それが予測できないということです。必ずしも結果をもたらすとは限りません。このようにクラッシュするのは良いことです。問題があることを知らせるからです。

デバッグとリリースをいじったり、コードの一部を追加または削除したり、最適化オプションを変更したりしても、問題が解決する可能性はほとんどありません。あったとしても、変更が加えられた場合に発生する可能性があります。

つまり、メモリ破損の問題があります。ほとんどの場合、それらを見つけるのは困難ですが、ツールはあります。その問題を解決する必要があります。

また、ショップの慣行を確認することもできます。安全性の低い構造 (newではなく配列vector<>など) を使用していますか? リスクを軽減するためのコーディング標準はありますか? コードレビューはありますか?メモリの破損は、危険で損害を与える可能性があるため、できる限り回避する必要があります。

于 2009-07-02T16:04:31.393 に答える
0

ここでの問題は、初期化されていないローカル変数だと思います。通常、デバッグ モードでは変数が初期化され、例外は発生しません。ただし、このため、リリース モードでエラーが発生する場合があります。

アクセスすると例外が発生する可能性がある、初期化されていない変数を探してみてください。

ブール型のローカル変数があるとします。

bool bRet;

デバッグ ビルドでは、bRet は 0 に初期化され、コードは問題なく動作します。

しかし、リリースでは 0 ではなく、ランダムな値であり、コードが bRet に基づいて何かを実行している可能性があります。 bRet 値が間違っているため、後で例外が発生する可能性があります。

于 2009-07-03T10:15:09.770 に答える
0

あなたが得ているのは、OSからのシステム例外です。これらは C++ の例外ではないため、処理されません。ただし、C++ 例外に変換して、通常の例外のようにキャッチすることができます。

http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/ (page 3) には、例外をキャッチする Windows Exception クラスの作成方法を示すすばらしい記事があります。メソッドを使用して_set_se_translatorC++ 例外をスローします。すばらしいことに、EXCEPTION_RECORD 構造からスタックを取得できますが、構造を処理するにはその機能を追加する必要がありますが、そのアクセス違反の検索を絞り込むのに役立ちます。

于 2009-07-02T17:02:03.263 に答える