デバックモード時の文字列変換について
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: &#128721; 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
回答を読ませていただいて、恥ずかしくなってしまいました。
一時オブジェクトであり、結果たまたま動いていただけという事実に強いショックを受けまして、
精進が足りない事を深く反省しております。

今後はより注意深くプログラムしていきたいと思います。
御迷惑をおかけしました。
丁寧に教えていただきまして、本当にありがとうございました。
編集
Reputeless  2020/05/05(Tue) 20:26
C++ の非直感的なところで、多くの人が間違えるところだと思います。
OpenSiv3D ではこうした誤りを防ぐために、可能な限りポインタを使わない API 設計にしています。
Win32 API の直接使用を回避するために、公式で採用してほしい機能があれば GitHub Issue, Slack 等でリクエストしてください。
編集
件名
Re: デバックモード時の文字列変換について
名前
コメント
画像添付


投稿修正キー (投稿を修正する時に使います)
画像認証 (右画像の数字を入力) 投稿キー

- WEB PATIO -