XcodeにおけるC++コードとデバッグとコンパイラオプション

以前に「OpenCVのコードを書く時にはC++で統一する」と宣言した。

OpenCVのコードをC++にすることによって

    • OOPになって画像やマトリクスを一貫してcv::Matクラスで扱えるようになった
    • テンプレートやコレクションクラスが使えるようになった
    • (最初は気味が悪かったが)コンストラクタが自動
    • 参照カウントによりインスタンスの明示的な解放が不要

等、便利でかつシンプルなコードを書けるようになったのだが、困ったことも起きていた。


これはOpenCVを使ったC++コードの中にXcodeブレークポイントを張って実行、ブレークした状態だが、全く見当違いな行で停止している。変数の監視も効かない。

どうしてこうなるのか。
色々と調べたが良く分からない。しかしこういう場合はコンパイル時の最適化が原因であることが多いと経験則で判っていたので、少し調べてみた。

Xcode(LLVM)コンパイルオプション


Xcodeのプロジェクト・ビルドオプションは現時点ではOptimization Level"-Os"に設定されているらしい。

このオプションの説明はここにある程度書かれているが、今ひとつ効果が良く分からないのでman pageを見てみる。
clang(1) OS X Developer Tools Manual Page

 Code Generation Options
   -O0 -O1 -O2 -Os -Oz -O3 -O4
       Specify which optimization level to use.  -O0 means "no optimization": this level compiles the
       fastest and generates the most debuggable code.  -O2 is a moderate level of optimization which
       enables most optimizations.  -Os is like -O2 with extra optimizations to reduce code size.  -Oz
       is like -Os (and thus -O2), but reduces code size further.  -O3 is like -O2, except that it
       enables optimizations that take longer to perform or that may generate larger code (in an attempt
       to make the program run faster).  On supported platforms, -O4 enables link-time optimization;
       object files are stored in the LLVM bitcode file format and whole program optimization is done at
       link time. -O1 is somewhere between -O0 and -O2.

それぞれに最適化とコードサイズに影響するオプションのようで、-Oの数値(又は英字)が最適化の強度を表しているらしい。

それぞれの意味?
  • O0 : 最適化無し。最も速くコンパイル出来、最もデバッガブルなコードを生成する
  • O1 : -O0と-O2の間 (実装依存?)
  • O2 : 多くの最適化が有効になる一般的な最適化
  • Os : -O2の最適化に加えてコードサイズを抑える
  • Oz : -Os、-O2に似ているが、更にコードサイズを抑える
  • O3 : -O2と似ているが、コンパイルに時間がかかるか、よりサイズが大きい、しかし性能の良いコードを生成する
  • O4 : リンク時最適化を有効にする

※意訳はいつもように適当なので、おかしかったらごめんなさい。

先ほどの最適化では"-Os"が設定されており、最適化+コードサイズを抑えるオプションのようだ。このせいでデバッグ時のブレーク行がおかしいのかもしれない。

ということで現在設定されている-Osから順に強度の低い方にオプションを変えていったが、最終的にブレーク行に正しく停止し、その後ステップ実行と変数の監視が正しく動作したのは "-O0"の最適化無しの状態だった。

同じブレークポイントで実行した結果

正しく設定したブレーク行で止まっており、C++オブジェクトによる変数も監視できている。(vectorの内容も正しくダンプできる)

この設定は最終的にはまた-Os等に戻すべきなのか、それとも最適化無しのままで良いのかまだ今ひとつ良く分かっていないが、正しくデバッグできるほうが先決なので、まずはこの設定で作業しようと思う。