VCのリリースビルドとデバッグビルドの違い

伊藤兎さんから昨日の日記(http://d.hatena.ne.jp/torazuka/20110816/cpp)にコメント頂いたのをきっかけに、リリースビルドとデバッグビルドを自分が理解していないことに気づいたので、調べました。そのメモです。

そもそも、「PDB(プログラムデータベース)ファイルを生成するのがデバッグビルドである」という誤解をしていました。

  1. リリースビルドでもデバッグ情報を生成できる
  2. デバッグ情報は、PDBでなくオブジェクトファイルに埋め込むこともできる

ということを知りました。

リリースビルドとデバッグビルドの操作上の違い

上の記事のとおり、[ソリューション構成]ドロップダウンリストの値を「Release」に変更してからビルドするのが、リリースビルドです。

[ソリューション構成]は、初期値で「Debug」がアクティブになっています。

開発は、基本的に「Debug」のまま行います。十分にデバッグをした後、リリース版の実行ファイルを取得したいときに、明示的にリリースビルドを実行します。…という認識です。

リリースビルドとデバッグビルドの実質上の違い

コードの最適化が行われるのが、リリースビルドです。

しかし、その結果、デバッグビルドでは起こらないエラーが発生する可能性があります。

上のページでは、リリースビルドとデバッグビルドでメモリアロケータが異なるために起きる問題や、VERIFYの代わりに重要な検証をASSERTに書いてしまっていた(その結果、リリースビルドでASSERTが評価されなかった)ことによる問題などが、解説されています。

デバッグビルドでは、メモリの上書きを検知するための機構が使われます。リリースビルドには、この機構がありません。特にこの違いが原因で、プログラムの挙動が異なるケースが多いそうです。

ただ、リリースビルド時とデバッグビルド時のコンパイラ動作の差異については、まだ資料を見つけていません。その1つが、伊藤さんが書いてくださった「初期化していない変数の自動初期化」だと思うのですが。

もう少し調べるか、デバッグビルドで生成されるアセンブリを比較すれば、確認できるかもしれません。

# ヲイ確認しろよって椅子蹴られそうですが、ちょっと本の裁断で忙しいので、今日のところは保留で…。

おまけ

その他、派生して覚えたことのメモです。

(その1)リリースビルドのデバッグ

リリースビルド時にも、次の方法でデバッグ情報を出力することができます。

これを使えば、リリースビルドでのみ観測できるバグの原因を調べるのに役立つかもしれません。

(その2)デバッグ情報の形式

デバッグ情報の形式には、次の3つがあります。

  1. C7互換
  2. プログラムデータベース
  3. エディットコンティニュのプログラムデータベース(※初期値)

これらは、[プロジェクト]→[プロパティ]→[構成プロパティ]→[C/C++]→[全般]の[デバッグ情報の形式]で確認・変更できます。

ちなみに、エディットコンティニュとは、このことですね。

エディット・コンティニューは(中略)、デバッギング セッションの途中でソース コードを変更し、デバッグ対象のアプリケーションにコードの変更を適用することができます。この際には、デバッギングを停止し、リビルドを行い、デバッガを再起動し、アプリケーションをバグが発生した状態にまで進めるといった操作は必要ありません。

Microsoft Visual C++ 6.0 の エディット・コンティニューによるデバッギングの強化

上のページによると、「ほとんどの最適化処理はエディット コンティニュと互換性がない」そうです。

リリースビルドではプログラムデータベース、デバッグビルドではエディットコンティニュのプログラムデータベースが、デバッグ情報の形式の初期値になっているのは、そのためでしょうか。

(その3)知っておくといつか役立ちそうな設定

だんだんどうでもいい話になってきましたが…面白そうだったやつ。

  • C/C++]→[出力ファイル]の[アセンブリ
  • [リンカー]→[詳細設定]の[プロファイル]
    • プロファイラを適用可能な出力ファイルを作成する。デバッグオプションと合わせて使う。
  • [リンカー]→[詳細設定]の[対象コンピューター]
    • 開発マシン以外の環境を想定したリンクができる。開発環境と実行環境が違う場合は、日常的に使う設定なのでしょう。