トップ回答者
_ismbclegal()

質問
回答
-
ドキュメントで明記されている範囲で動作が変わったのであれば仕様変更か不具合かになりますが、どちらかを確定するためには Microsoft 側の情報が必要となり、公開情報を探すか、サポートで聞き出すかになります。
ドキュメントに書かれていないことは仕様未定義なのでその動作が変わったとしても仕様未定義のままなので仕様変更とはなりません。
今回の件は渡す数値がドキュメントで正しい文字に限定されていないとはいえ、無保証の範囲かな?と思います。恐らく、内部の実装が変わったのでしょうね。
- 回答としてマーク k-z-m 2019年1月17日 0:47
-
ucrtのソースをみると、ucrt内部で参照するテーブルへのアクセスマクロから、 16299までにはあったunsigned charへのキャストが、17763では消えてますね。
mbclegal側は、_ismbblead_l(c>>8, ...) 的な呼び出しだから65535を超えると溢れるのでしょう。
corecrt_internal_mbstring.h
(17763)#define _ismbblead_l(_c,p) ((p->mbcinfo->mbctype + 1)[_c] & _M1)
(10240)#define _ismbblead_l(_c,p) ((p->mbcinfo->mbctype + 1)[(unsigned char)_c] & _M1)
jzkey
すべての返信
-
Windows 10 x64 1803 ビルド 17134.471 で確認してみましたが、_ismbclegal に半角2文字分の char を次の計算式で渡してもエラーとはなりませんでした。
_ismbclegal(szText[1]+(szText[0]<< 8));
エラーとなるときの _ismbclegal 関数の引数に渡される数値は具体的になにでしょうか?また、「APエラー」とは具体的にはどういった状態でしょうか?例外が発生する?あるいはアプリケーションが落ちる?応答なし?
再現する Windows の情報をもう少し詳しく教えてください。ユーザーロケール、システムロケールは何でしょうか?64・32ビットなど。
追伸:本現象と関係あるかわかりませんが、Windows SDK のバージョンによって _ismbclegal に本来あり得ないような数値を渡すと例外が発生することがわかりました。
__try { int nRet = _ismbclegal(99342080); } __except(EXCEPTION_EXECUTE_HANDLER) { // Windows SDK バージョンが 10.0.17763.0 のとき例外発生する }
例外が発生するのは、Windows SDK バージョンが 10.0.17763.0 のときで、それ以外では確認できませんでした。確認したバージョンは 10.0.16299.0、10.0.17134.0、10.0.17763.0、8.1。- 編集済み kenjinoteMVP 2019年1月10日 13:05
-
ドキュメントで明記されている範囲で動作が変わったのであれば仕様変更か不具合かになりますが、どちらかを確定するためには Microsoft 側の情報が必要となり、公開情報を探すか、サポートで聞き出すかになります。
ドキュメントに書かれていないことは仕様未定義なのでその動作が変わったとしても仕様未定義のままなので仕様変更とはなりません。
今回の件は渡す数値がドキュメントで正しい文字に限定されていないとはいえ、無保証の範囲かな?と思います。恐らく、内部の実装が変わったのでしょうね。
- 回答としてマーク k-z-m 2019年1月17日 0:47
-
ucrtのソースをみると、ucrt内部で参照するテーブルへのアクセスマクロから、 16299までにはあったunsigned charへのキャストが、17763では消えてますね。
mbclegal側は、_ismbblead_l(c>>8, ...) 的な呼び出しだから65535を超えると溢れるのでしょう。
corecrt_internal_mbstring.h
(17763)#define _ismbblead_l(_c,p) ((p->mbcinfo->mbctype + 1)[_c] & _M1)
(10240)#define _ismbblead_l(_c,p) ((p->mbcinfo->mbctype + 1)[(unsigned char)_c] & _M1)
jzkey