22450


Gentoo linuxのドキュメントに下記のような説明がありました。  
字義通り解釈すると「コンパイル時最適化を無効(`-O0`)にすると正常動作しないアプリケーションがある」とのことですが、実際にそのようなパッケージ（アプリケーション）は存在するのでしょうか？

<https://wiki.gentoo.org/wiki/GCC_optimization>

> `-O0:` This level (that is the letter "O" followed by a zero) turns off
> optimization entirely and is the default if no `-O` level is specified in
> CFLAGS or CXXFLAGS. This reduces compilation time and can improve debugging
> info, but **some applications will not work properly without optimization
> enabled.** This option is not recommended except for debugging purposes.

個人的には、最適化無効状態で正常動作しない＝そもそも壊れたプログラムという感覚なのですが...


CC BY-SA 4.0
2016-02-23T14:56:29.697
22446
2018-06-19T10:34:50.887
2018-06-19T10:34:50.887
12216
49
question
c gcc gentoo
最適化を無効化(-O0)すると動作しないアプリケーション？


抽象的な回答になってしまいますが。

規格上、未定義・不定・実装依存とされてしまうような書き方をしていると、コンパイラやプラットフォームが変わって動作しなくなるというのはありがちで、最適化オプションの指定によっても変わるというのは十分あり得る話だと思います。

代入文の左辺と右辺の評価順、関数の引数の評価順 (いずれも不定) あたりは、優秀なプログラマでもついやってしまうようで、mrubyでもあったようです。  
<https://codeiq.jp/magazine/2013/12/3556/>  
(ただ、これが最適化オプションの違いで起きるかは不明です。)

ちなみに、「最適化が無効になっていると動作しないアプリがある」ですよね? (どちらかといえば、最適化によって壊れることの方が多いですが。)


CC BY-SA 3.0
2016-02-23T15:46:37.440
22447
2016-02-23T15:46:37.440
76
22446
answer


StackExchange の Unix&Linux コミュニティで [Linux cannot compile without GCC
optimizations;
implications?](https://unix.stackexchange.com/questions/153788/linux-cannot-
compile-without-gcc-optimizations-implications) というのを見つけました。これによると、Linux
のカーネルのビルドは、不要なコードの削除や関数のインライン展開などのGCC の最適化に依存しており、`-O0` だとビルドに失敗するそうです。


CC BY-SA 3.0
2016-02-23T19:19:23.377
22450
2016-02-23T19:19:23.377
2017-04-13T12:37:20.867
-1
3605
22446
answer


パッと思いつく例としては、末尾最適化を前提とした再帰呼び出しでしょうか。  
この場合もちろんコンパイルは通りますが、実行時には再帰呼び出しによりコールスタックを食い潰しスタックオーバーフローを引き起こします。


CC BY-SA 3.0
2016-02-23T20:29:50.500
22451
2016-02-24T07:42:18.970
2016-02-24T07:42:18.970
4236
4236
22446
answer


x86ではdoubleの演算はFPUに乗る時に80bitに拡張されます(FPU制御レジスタの設定によりますが、Linuxではデフォルトで拡張されるようになっていたはず)。計算の途中結果を一時変数に代入している場合、最適化無しだと代入の際に64bitに丸められてそれが続きの計算で使われますが、最適化ありだとFPUのレジスタに乗っている80bitの値をそのまま使われ、演算結果が異なる可能性があります。通常のプログラムでは浮動小数点数演算の誤差として片付けられるのですが、まれにこの差が問題となることがあります。

実例として、浮動小数点数の正確かつ最適な表示
(与えられた浮動小数点数が表現し得る幅の中で、最も短い10進数表記を求める)アルゴリズムは、64bitのdoubleを扱うためには64bitより大きい精度を必要とします。計算途中で10倍する際に、仮数部の有効数字が1bit余計に必要になるためです。最適化無しで中間結果をdouble型変数に代入すると途中で丸めが入っておかしくなりますが、中間結果が80bitのまま保持されると正しい結果が得られます。Scheme処理系SCMがかつてそのような実装になっていました(参考:[1](https://practical-
scheme.net/wiliki/wiliki.cgi?Gauche%3A%E6%8B%A1%E5%BC%B5%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%BC%94%E7%AE%97%E3%81%AE%E8%AC%8E)。現在の実装は多倍長整数を使っているのでこの問題はもうありません。)

もちろんコード作法的には良くない実装です。コンパイラとプロセッサを決め打ちできる案件ならともかく、今はデスクトップではx86_64の方が主流になり「最適化で80bitのまま保持されることをあてにする」という手法自体obsoleteと考えて良いと思います。


CC BY-SA 3.0
2016-02-23T20:59:49.193
22452
2016-02-23T20:59:49.193
5258
22446
answer