前提・実現したいこと
Visual Studio 2013を用いて、C++/MFCアプリケーションを開発しています。
とあるプロジェクトにおいて、Releaseモードのみ発生するバグが見つかりました。
原因を特定した所、Releaseモードにおいて意図しない動作をしているコードが発見でき、それによって引き起こされるバグと判明しました。
以下が、原因箇所のミニマムなコードです。
cpp
1// 引数に与えた値の中から最大値を取得する可変長template関数 2template<typename Ty> 3Ty GetMax(const Ty& left, const Ty& right){ 4 return (left < right) ? right : left; 5} 6 7template<typename Ty, typename... Ts> 8Ty GetMax(const Ty& num, const Ty& num2, const Ts&... nums){ 9 return GetMax(GetMax(num, num2), nums...); 10} 11 12//実装コード 13CString str(_T("hoge")); 14CString str2(_T("dog")); 15CString str3(_T("be")); 16 17int max_length = GetMax(str.GetLength(), str2.GetLength(), str3.GetLength());
実行時、max_length
をキャプチャした所、Debugモードでは4
を示し、Releaseモードでは意図しない値(例えば5488576
など)が観測されました。
- 補足
一度変数に代入するという回避策を頂きました。
例えば以下のような感じです。
cpp
1CString str(_T("hoge")); 2CString str2(_T("dog")); 3CString str3(_T("be")); 4int size1 = str.GetLength(); 5int size2 = str2.GetLength(); 6int size3 = str3.GetLength(); 7 8int max_length = GetMax(size1, size2, size3); //4が入る
これだと確かにコンパイルは通り、実行結果も上手く行きます。
しかし、何故直接では駄目で一度変数に逃がす必要があるのかわからないので、依然として納得できません。
疑問
- まず何故このような結果になってしまうのか。
- Debugモード / Releaseモードで挙動が違う?検討が付きません。
- 補足コードのようにすると実行結果は上手くいくが、何故直接
GetLength()
からでは駄目なのか
補足情報
- Windows 7 Pro SP1 64bit
- Visual Studio 2013( Version 12.0.40629.00 Update 5 )
- リンカー / 最適化オプションが以下の通りです
項目 | Debug | Release |
---|---|---|
参照 | なし | はい(/OPT:REF) |
COMDATの圧縮 | なし | はい(/OPT:ICF) |
上記以外で必要な情報があれば追記します。
分かる方いらっしゃったら、回答の方よろしくお願いします。
回答5件
あなたの回答
tips
プレビュー