方法 : 最適化されたコードをデバッグする
更新 : 2007 年 11 月
このトピックの内容は、次の製品に該当します。
Edition |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express |
ネイティブのみ |
|||
Standard |
ネイティブのみ |
|||
Pro/Team |
ネイティブのみ |
表の凡例 :
対象 |
|
該当なし |
|
既定で非表示のコマンド |
メモ : |
---|
使用している設定またはエディションによっては、表示されるダイアログ ボックスやメニュー コマンドがヘルプに記載されている内容と異なる場合があります。設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。詳細については、「Visual Studio の設定」を参照してください。 |
コンパイラは、ソース コードを最適化するときに命令を再配置したり再構成したりします。これにより、コンパイル後のコードの実行効率が向上します。しかし、この命令の整理が原因となり、一連の命令に対応するソース コードをデバッガが識別できなくなる場合があります。
最適化によって次のような影響が生じる場合があります。
ローカル変数がオプティマイザによって削除されたり、デバッガの追跡できない場所に移動されたりする可能性があります。
オプティマイザによってコード ブロックがマージされた場合、関数内の位置が変更されます。
オプティマイザによって 2 つの関数がマージされた場合、呼び出し履歴上のフレームに対し、間違った関数名が表示される場合があります。
ほとんどの場合、呼び出し履歴上のフレームには、正しい情報が表示されます。ただし、これはすべてのフレームにシンボルが割り当てられていることが前提となります。スタックの破損が生じた場合、アセンブリ言語で記述された関数が存在する場合、呼び出し履歴上のシンボルに一致しないオペレーティング システムのフレームが存在する場合など、呼び出し履歴上のフレームに誤った情報が表示されることがあります。
グローバル変数および静的変数は常に正しく表示されます。構造体レイアウトについても同様です。構造体へのポインタが存在し、そのポインタの値が正しければ、構造体のすべてのメンバ変数は、正しい値で表示されます。
これらの制限事項のため、できるだけ最適化する前のプログラムをデバッグするようにしてください。最適化に対する既定の設定は、Visual C++ のデバッグ構成ではオフ、リリース構成ではオンになっています。
ただし、最適化後のプログラムでしかバグが発生しない場合もあります。このような場合は、最適化されたコードをデバッグする必要があります。
デバッグ ビルド構成で最適化をオンにするには
新しいプロジェクトの作成時に、Win32 Debug ターゲットを選択します。プログラムが完全にデバッグされ、Win32 Release ターゲットをビルドできるようになるまでは、Win32Debug ターゲットを使用します。コンパイラは、Win32 Debug ターゲットの最適化は行いません。
ソリューション エクスプローラでプロジェクトを選択します。
[表示] メニューの [プロパティ ページ] をクリックします。
[プロパティ ページ] ダイアログ ボックスで、[構成] ボックスの [Debug] が選択されていることを確認します。
左側のフォルダ ビューで、[C/C++] フォルダを選択します。
[C/C++] フォルダの下の [Optimization] を選択します。
右側のプロパティ リストで、[Optimization] を探します。その横の設定値は、[Disabled] (/Od) になっているはずです。その他のオプション ([Minimum Size] (/O1)、[Maximum Speed] (/O2)、[Full Optimization] (/Ox)、[Custom]) から 1 つを選択します。
[Optimization] に対して [Custom] オプションを選択すると、プロパティ リストに表示されているその他のプロパティについてオプションを設定できるようになります。
最適化されたコードをデバッグするときは、実際にどのような命令が作成および実行されているのかを [逆アセンブリ] ウィンドウで確認してください。ブレークポイントを設定する場合は、ブレークポイントが命令と共に移動する可能性があるため注意が必要です。たとえば、次のコードがあるとします。
for (x=0; x<10; x++)
この行にブレークポイントを設定したとします。ブレークポイントは 10 回ヒットするように思われますが、このコードを最適化した場合は、ブレークポイントは 1 回しかヒットしません。これは、コンパイラが、x の値を 0 に設定する最初の命令を 1 回だけ実行するものと見なしてループの外に移動するためです。このとき、ブレークポイントもこの命令と共に移動します。
x を比較してインクリメントする命令はループ内に残ったままになります。[逆アセンブリ] ウィンドウを参照すると、コードの実行をより細かく制御できるように、ステップ実行の単位が自動的に命令に設定されています。この設定は、最適化されたコードをステップ実行するときに役立ちます。