none
_ismbclegal() RRS feed

  • 質問

  •  _ismbclegal() についてです。

    文字列から2バイト分を取り出し、上記関数に引数で渡した際に、

    全角文字(2バイト)の場合は、OSのバージョンに関わらず、「1」(0以外)を返します。

    しかし、取り出した2バイトが半角文字(1バイト)2文字分である場合に、

    Win10 1709版まではAPエラーにはなりませんでしたが、

    1803版では「0」を返さずにAPエラーになってしまいます。

    仕様変更などがあったのでしょうか?

    よろしくお願いします

    2019年1月10日 8:12

回答

  • ドキュメントで明記されている範囲で動作が変わったのであれば仕様変更か不具合かになりますが、どちらかを確定するためには Microsoft 側の情報が必要となり、公開情報を探すか、サポートで聞き出すかになります。

    ドキュメントに書かれていないことは仕様未定義なのでその動作が変わったとしても仕様未定義のままなので仕様変更とはなりません。

    今回の件は渡す数値がドキュメントで正しい文字に限定されていないとはいえ、無保証の範囲かな?と思います。恐らく、内部の実装が変わったのでしょうね。

    • 回答としてマーク k-z-m 2019年1月17日 0:47
    2019年1月16日 3: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


    • 編集済み jzkey 2019年1月16日 5:16 改行
    • 回答としてマーク k-z-m 2019年1月17日 0:47
    2019年1月16日 5:15

すべての返信

  • 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。

    2019年1月10日 12:35
  • 情報ありがとうございます。

    「APエラー」はアプリケーションが落ちているのですが、プロセスは残ります。

    再現するのは、Windows 10 x64 1803 で、ビルド番号に関係なく発生します。

    _ismbclegal にどのような値が渡っているか確認したところ、「4294937837」でした。

    ありえない数値なので、「追伸」の内容が発生していると思われます。

    環境で調べたところ、

     ucrtbase.dll10.0.17134.319

     SDK version 8.1.23107

    でした。

    2019年1月11日 1:45
  • 仕様変更があったと考えたほうがいいでしょうか?
    2019年1月15日 8:46
  • ここでは Microsoft の公式回答はありません。
    従って、その質問に対しては誰も答えを返せません。

    ご自身の責任でご判断ください。
    それでは足りない場合は有償サポートで聞き出すなど、適切なアプローチをとってください。

    2019年1月15日 12:48
    モデレータ
  • 失礼いたしました。

    2019年1月16日 2:13
  • ドキュメントで明記されている範囲で動作が変わったのであれば仕様変更か不具合かになりますが、どちらかを確定するためには Microsoft 側の情報が必要となり、公開情報を探すか、サポートで聞き出すかになります。

    ドキュメントに書かれていないことは仕様未定義なのでその動作が変わったとしても仕様未定義のままなので仕様変更とはなりません。

    今回の件は渡す数値がドキュメントで正しい文字に限定されていないとはいえ、無保証の範囲かな?と思います。恐らく、内部の実装が変わったのでしょうね。

    • 回答としてマーク k-z-m 2019年1月17日 0:47
    2019年1月16日 3: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


    • 編集済み jzkey 2019年1月16日 5:16 改行
    • 回答としてマーク k-z-m 2019年1月17日 0:47
    2019年1月16日 5:15
  • 皆様

    ご指導、ご教授ありがとうございます。

    お教えいただいた内容をもとに対応を検討したいと思います。

    2019年1月16日 6:25