この質問には、バグがリリース ビルドでのみ現れる理由を説明する多くの優れた回答があります。
リリース バージョンのバグがデバッグ モードに存在しない一般的な理由
未定義の動作に関して、より具体的な質問があります。
プログラムがデバッグ ビルドでは常に正しく動作しているように見えても、リリース ビルドでは動作が異なる (ただし、常に同じように正しく動作しない) 場合、問題は未定義の動作が原因である可能性がありますか?
この質問には、バグがリリース ビルドでのみ現れる理由を説明する多くの優れた回答があります。
リリース バージョンのバグがデバッグ モードに存在しない一般的な理由
未定義の動作に関して、より具体的な質問があります。
プログラムがデバッグ ビルドでは常に正しく動作しているように見えても、リリース ビルドでは動作が異なる (ただし、常に同じように正しく動作しない) 場合、問題は未定義の動作が原因である可能性がありますか?
未定義の動作が原因でしょうか? もちろん。それは常に未定義の動作のためですか? 確かにそうではありません。
これを想像してください:
assert(scanf("%d", &n) == 1);
この行は、リリース モードで単純に削除されます。これは未定義の動作ではありませんが、プログラムが異なる方法で動作することは間違いありません。
assert
ここでは明らかな例かもしれませんが、次のより複雑な状況を考えてみてください。
#ifndef NDEBUG
# define DBG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
# define DBG(fmt, ...) ((void)0)
#endif
int shared_var;
static inline void do_something_fast(void)
{
DBG("doing something fast\n");
shared_var = something_fast();
}
スレッド1を持っています:
...
mutex_unlock();
local_var = shared_var;
...
およびスレッド 2:
...
mutex_lock();
do_something_fast();
...
この例はまったくばかげていますが、これらの線に沿ったものはマルチスレッド環境では非常に一般的です。この例では、次のようになります。
shared_var
ますlocal_var
shared_var
shared_var
ますlocal_Var
ご覧のとおり、この例では I/O をブロックすることでスレッド間で特定の動作が強制され、それ自体はデバッグ モードでのみ有効になっていました。これは、デバッグで動作するプログラムが、リリース用にコンパイルされたときとは異なる動作をする可能性があることも意味します。