Edited at

C++において遭遇した分かりにくいバグの忘備録

More than 3 years have passed since last update.



現象

デバッグビルドでは不具合がでないのに、リリースビルドにすると不具合がでる。



原因

変数の初期化を忘れていた。

デバッグビルドでは初期化を忘れていても、0に初期化されることが多いため不具合が発現しない。コンパイラが初期化忘れを警告できない場合があるので注意。




現象

文字列バッファが任意のタイミングでAccess Violationを起こす



原因

std::string.c_str()を保持して、他で使っていた。

c_str()で得たバッファは元のstringが解放されるとその後の任意のタイミングでfreeされる。他で使う場合には複製しなければならない。freeのタイミングが任意なので、バグが発現しにくい。特にc_str()のバッファの一部をポインタとして保持する場合に注意。




現象

別のコンパイラでビルドしたら、関数の戻り値を変数に代入したはずなのに、タイミングによって代入されない場合があった。

struct s {
size_t index;
string str;
};
vector<s> v;
v[0].index = func(v); // func()が1を返す
// v[0].indexが1にならない


原因

func()内でvに要素を追加していたために、vectorの再配置により代入先が変化していた。

この場合はvectorの要素が構造体なのがミソで、代入先の参照がfunc()実行より前に確保されていた。この動作はコンパイラによって異なるので、特定のコンパイラでのみ不具合が発現した。
(構造体の要素ではなくて、v[0]に直接代入するコードも駄目かも。v[0]で要素への参照が先に確保されてしまう可能性があるから)