none
中身のない関数や、到達しない処理に対する最適化の機能 RRS feed

  • 質問

  • こんにちは。

    プロガードで実体の無い関数や到達しないブロックを削除するという機能がありますが、

    Visual Studio の最適化でそういった事は可能でしょうか?

    今までデバッグ用の処理などはマクロの呼び出しで行い、リリース時には
    マクロの定義部分が空になるようにしていました。
    しかし、
    最近、デファインを極力へらそうとしています。(ソースを見た時、全て大文字だと
    分かりづらい、名前が被る等の理由で)
    そういった処理を関数にして、その中身がリリース時に空になるようにした場合、中身の無い関数の定義や呼びだし
    の扱いがどうなるかが気になります。

    そういった機能の有無
    消えない場合、プログラムに対する影響(動作やサイズなど)

    ご存知の方、いらっしゃいましたらご教授いただけると幸いです。
    2008年12月17日 3:20

回答

  • レスつきませんねぇ。

    やってみればすぐにわかりますが、リンカは必須コード(関数)が

    依存しないコード(関数)はリンクしません。

     

    必須コードとは

     1.スタートアップ関数 ( main() WinMain()DllMain()等)

     2.DLLのExportされた関数

     3.スレッド関数

    等があります。

     

    翻訳された*.objには、ソース内の(有効な)全てのコードが含まれますが、

    このコードの全てがリンクされるわけではありません。

    リンクされるかどうかは、関数の中身のある無しにではなく、

    その関数が必須関数からの一連の依存関係において、1度でも呼ばれたかどうかに

    関係します。もちろん、一般のクラスメンバ関数も例外ではありません。

     

    最適化のオプションによっては、中身の無い関数は除外されるかも

    しれませんが、詳しくはわかりません。あしからず。

     

    呼ばれないコード上にブレークポイントをはって実行してみると、

    このブレークポイントが無効になることで、ある程度納得できるでしょう。

     

    2008年12月17日 6:27
  • 実行ファイルに関数が含まれているかはMAPファイルで確認できます。

    リンカのオプションでMAPファイルを生成する設定にしてビルドするとMAPファイルができます。

    MAPファイルを適当なエディタで開いて関数名で検索し、見つからなければ実行ファイルに含まれてないかインライン展開されたかのどちらかと考えて良いと思います。

     

     

    2008年12月17日 13:37

すべての返信

  • レスつきませんねぇ。

    やってみればすぐにわかりますが、リンカは必須コード(関数)が

    依存しないコード(関数)はリンクしません。

     

    必須コードとは

     1.スタートアップ関数 ( main() WinMain()DllMain()等)

     2.DLLのExportされた関数

     3.スレッド関数

    等があります。

     

    翻訳された*.objには、ソース内の(有効な)全てのコードが含まれますが、

    このコードの全てがリンクされるわけではありません。

    リンクされるかどうかは、関数の中身のある無しにではなく、

    その関数が必須関数からの一連の依存関係において、1度でも呼ばれたかどうかに

    関係します。もちろん、一般のクラスメンバ関数も例外ではありません。

     

    最適化のオプションによっては、中身の無い関数は除外されるかも

    しれませんが、詳しくはわかりません。あしからず。

     

    呼ばれないコード上にブレークポイントをはって実行してみると、

    このブレークポイントが無効になることで、ある程度納得できるでしょう。

     

    2008年12月17日 6:27
  • お返事ありがとうございます。

     仲澤@失業者 さんからの引用

    呼ばれないコード上にブレークポイントをはって実行してみると、

    このブレークポイントが無効になることで、ある程度納得できるでしょう。



    確かに無効になりました。
    試しに簡単な文字表示のコードを含んだ関数をつくり、
    その中身を空にした時と逆アセンブリの結果を見比べたところ、
    中身があるときはアセンブリで処理が書かれているのですが、
    中身を空にすると、アセンブリの記述が終了処理だけになっているようにみえました。
    (逆アセンブリをちゃんと使ったことがないので自信がないですが...)

    これは機能していない関数の呼び出しが除外され、実行ファイルに含まれていない
    と考えてよろしいのでしょうか?
    2008年12月17日 7:34
  • 実行ファイルに関数が含まれているかはMAPファイルで確認できます。

    リンカのオプションでMAPファイルを生成する設定にしてビルドするとMAPファイルができます。

    MAPファイルを適当なエディタで開いて関数名で検索し、見つからなければ実行ファイルに含まれてないかインライン展開されたかのどちらかと考えて良いと思います。

     

     

    2008年12月17日 13:37
  • お返事ありがとうございます。

    MAPファイル… こんな機能があったのですね。 知りませんでした。
    早速使ってみたところ、組み込み型が引数の空関数の呼び出しは完全に
    無視されるようですが、クラスなどが引数だとコンストラクタか何かが
    呼ばれてるようですね。

    やはり、デバッグ時に完全に消したい処理はデファインを使った方がいいようですね。
    名前の問題は、C# の影響でキャメル書式で書いていたのも問題ですので、
    これからはマクロ関数を書く時は、多少見づらくても極力すべて大文字にし、
    冗長になっても名前が被らず、使用箇所が分かりやすい名前をつけようと思います。

    みなさん、アドバイスありがとうございました!
    2008年12月19日 1:36