2013-05-22 9 views
12

Visual Studioから直接実行すると、実行可能ファイルが繰り返し出力可能な問題をデバッグしようとしていますが、ではありません。は、コマンドプロンプトから実行されたときこれはシングルスレッドのアプリケーションなので、タイミングに関して奇妙な動作があってはいけません。Visual Studioデバッガと実行可能ファイルをデバッガなしで実行する場合の違い

誰かが2つの環境の間にどのような違いがあるのか​​を列挙できますか?

私は実際の実行可能ファイルは同じであると確信しています - 両方ともリリースビルドで、同じ.exeファイルを実行しています。ここで

は、環境と結果は以下のとおりです。

  1. コマンドプロンプト(CMD)から直接実行:デバッグ(F5)を使用してVisual Studioから非反復性出力
  2. ラン:反復出力
  3. ランVisual Studioからデバッグなし(Ctrl-F5):非反復出力

作業ディレクトリが異なる可能性がありますが、作業ディレクトリでは同じです。

これらの結果に基づいて、「デバッグを使用して」(リリースビルドでも)実行されているように見えますが、何らかの形で問題が修正されています。これは可能性のある犯人を指していますか?実行可能ファイルをデバッグで実行する場合と実行しない場合の違いは何ですか?

解決策:受け入れられた回答で指摘したように、デバッグヒープが問題でした。問題はコードの深いところにあり、誰かが初期化される前に大きな配列の一部にアクセスしていたということでした。彼らはmallocでメモリを割り当てていて、メモリを0に初期化していませんでした。デバッグヒープは配列をいくらかの反復可能な値で埋めていましたが、デバッガが接続されていないとき(つまりコマンドラインからCtrl + F5)、値がランダムになり、プログラムの動作に小さな偏差が生じることがありました。残念ながら調整はほとんど目立たない程度に微妙で、問題のメモリが処理の最初の「フレーム」の後で正しくリセットされましたが、初期条件はすでにわずかに異なり、損傷が行われていました。アクションのカオス理論!ガイダンスをありがとう。

偉大なデバッグのヒント:メモリを完全にランダムなデータで即座に埋め込むカスタムmallocを作成しました。そうすれば、使用する前に自分自身を適切に初期化していることを確認することができます。そうしないと、デバッグヒープを使用してデバッグモードでも結果がうまくいきません。

+1

コードによって異なります。より高い最適化レベルでのみ動作する未定義の動作を引き起こしている可能性があります。 –

+1

しかし理論的には、デバッガが接続されていないという唯一の違いはありませんか?ビルドは同じです - 両方のビルドをリリースします。最適化の程度は変わりません。 – aardvarkk

+0

私はあなたが作業ディレクトリを調整していると言いますが、それはおそらく原因と思われます。私が探している他の問題は、インストールされたライブラリです。 VSは依存関係を処理します(また、ClickOnceを使用してビルドしてインストールする場合、依存関係を処理します)。ただし、コマンドラインで直接実行することはできません。 –

答えて

15

Windows Heap behaves differently if process is started under the debugger.この動作を無効にするには(デバッグ中に問題を見つけるために)_NO_DEBUG_HEAP = 1を環境に追加してください(this questionなど)。

また、プログラム実行の早い段階でプロセスにアタッチすることもできます。ヒープはデバッグモードに入りません。実行の始めのどこかにDebugBreak()行を追加し、Ctrl + F5で実行し、要求されたらデバッグを開始します。

+0

これは素晴らしいヒントのようです - 私はそれを試してみるよ、ありがとう! – aardvarkk

+0

そこにも素晴らしいリンクが追加されています。これは私には非常によく似た問題です - デバッガが接続されたときに反復可能なセンチネル値がありますが、そうでなければガベージデータだけです(したがって、反復不可能な動作です)。 – aardvarkk

+0

これは正しい方向に私を指摘しました。私はいくつかの詳細で質問を編集します。ありがとう! – aardvarkk

0

まあ、あなたのコードについてもう少し分かっていなくても、言うことは難しいです。しかし、多くの浮動小数点演算(倍精度数値)を実行するプログラムでも同様の問題がありました。

私はわずかに異なる番号を扱っていたが、数値的にはマシンの区別がつかなかったときに問題が発生する。 2つの倍数がnumeric_limits<double>::epsilon()未満で異なる場合、それらはマシンの同じ番号と見なされます。したがって、タイプの表現:

if (num1==num2)... 

または

if (num1<num2)... 
... 

はカラフルな効果をもたらす可能性があります。

これらのカラフルなエフェクトは、デバッグモードまたはリリースモードで実行すると異なります。その理由は、デバッグ/リリースランタイムライブラリが異なるからです。また、決定的には、コンパイルはさまざまなコードの最適化で行われます。コマンドラインデバッグバージョンとデバッグウィンドウバージョン(F5)の違いは、微妙な最適化の違いによっても説明されます。

VSを使用している場合は、PropertiesメニューのC/C++Linkerセクションで、さまざまなコンパイルオプションと最適化の効果を確認できます。

この問題を回避するには、<limits> STLライブラリのnumeric_limits機能を使用することをおすすめします。例として、より小さい演算子の実装は、次のようなものになります。

bool operator<(double num1, double num2) { 
    double difference=fabs(num1-num2); 
    if (difference>numeric_limits<double>::epsilon()) { 
     if (num1 < num2) return true; 
     return false; 
    } 
    return false; 
} 
関連する問題