デバックモード時の文字列変換について
furafura 2020/05/03(Sun) 18:39
お世話になっております。
リリースとデバッグモードで挙動が異なるので質問があります。
とりあえず「○」のような記述で意図した動作となるため、
返信いただけなくても構いません……。
「本件」ソースです。
# include <Siv3D.hpp> // OpenSiv3D v0.4.3
#include <windows.h>
void Main()
{
const String text = U"E:/作品/P3242166.tif";
// [○]
const std::wstring wstr = text.toWstr();
const LPCWSTR imageFileName = wstr.c_str();
// [×]
const LPCWSTR imgf = text.toWstr().c_str();
while (System::Update())
{
}
}
リリース時ではコメント[○][×]でも同じ挙動、
詰まりimageFileNameとimgfの内容は一致するかと思います。
問題のデバッグ時ですが、コメントで[○][×]で挙動が異なるものと思います。
私の使い方・理解が間違っているのかわからないので、教えていただけると幸いです。
元々「別件」にて、リリースモード時
90013: 🛑 Application terminated due to an exception `EXCEPTION_INT_DIVIDE_BY_ZERO`
が出てしまったので、デバッグモードで原因を探れないかと考えた矢先に遭遇した現象です。
この「別件」はまだ未解決……(涙)。
Reputeless 2020/05/04(Mon) 00:54
誤ったプログラムが原因です。[〇] に書かれた方法が正しいです。
const wchar_t* imgf = text.toWstr().c_str();
では、text.toWstr() で作成される std::wstring 型の一時オブジェクトが持つ文字列のポインタを取得しています。
オブジェクトはその行で破棄されるので、それ以降ではポインタは無効となり、使用すると未定義動作です。
未定義動作では何が起こるかは決まっていないので、期待した動作は得られません。
(Release ビルドでは、偶然コンパイラが text.toWstr() の一時オブジェクトのデータのクリアを最適化のため省略し、ポインタの指す先に元のデータが残されていたため、正しく動いているように見えただけです)
furafura 2020/05/05(Tue) 17:55