sprintf + utf8 + "取得" でアサーションエラー

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
C++er

sprintf + utf8 + "取得" でアサーションエラー

#1

投稿記事 by C++er » 3ヶ月前

日本語Win10でvisual studio 2017 C++ を使っていますが、以下のコードを実行すると、

int WINAPI WinMain(HINSTANCE hCurrInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
setlocale(LC_CTYPE, ""); //<--- SJIS
char s[16];
sprintf(s, u8"取得");
return 0;
}

sprintf 内でアサーションエラーが起きます。

>>>>>>>>>
Debug Assertion Failed!

Program: D:\test\test.exe
File: minkernel\crts\ucrt\inc\corecrt_internal_stdio_output.h
Line: 1700

Expression: _format_char != '\0'

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

<<<<<<<<<
setlocale を削除するか、sprintf(s, "%s", u8"取得") とすれば直るのですが、
何故エラーが起きるのでしょうか??

"取得" という文字列はutf8にすると E58F96 E5BE97 ですが、
とくにSJISでの危険な文字と重なっているようにも思えません。

Bull
記事: 124
登録日時: 5年前

Re: sprintf + utf8 + "取得" でアサーションエラー

#2

投稿記事 by Bull » 3ヶ月前

ソースファイル (corecrt_internal_stdio_output.h) を詳細に読んだわけでないのですが、ロケールよっては?、printf 系の関数は書式文字列の整合性をチェックするようです。
u8"取得"のバイト列を Shift_JIS として解釈すると E58F(蜿) 96E5(門) BE(セ) 97 00 となります、97 はマルチバイト文字の1バイト目ですが、次が null 文字であるためエラーになっているようです。

c++er

Re: sprintf + utf8 + "取得" でアサーションエラー

#3

投稿記事 by c++er » 3ヶ月前

なるほど、言われてみれば確かにそうです。
これでスッキリしました

ちなみに新規作成した、デフォルト設定状態のプロジェクトで実行したら普通に通ったので、SDK (141_xp) やライブラリの設定legacy_stdio_definitions.libなどの組み合わせによって、sprintfのチェック機構が異なるのかもしれません。

ありがとうございました

c++er

Re: sprintf + utf8 + "取得" でアサーションエラー

#4

投稿記事 by c++er » 2ヶ月前

追記です。

上で、「新規プロジェクト作成では再現しなかった」と書きましたが、
「プロジェクト→プロパティ→C/C++→コード生成→ランタイムライブラリ」の設定を「マルチスレッドデバッグDLL」ではなく「マルチスレッドデバッグ」にすると再現しました。

DLLを使うかそうでないかで組み込みマクロの定義が変わり、ヘッダに記述されている sprintf(から呼ばれてる関数)の挙動が変わるみたいですね。

返信

“C言語何でも質問掲示板” へ戻る