バグレポートを、もひとつどうぞ

id:logion:20060805#p4 で公約した WideChar/Multibyte 変換の問題(id:logion:20060209#p2) を報告してみました。(#32177) ただ再現するテストプログラムを書くのを面倒臭がっていた訳ですが、報告せずいつまでも胸の中にしまっておくのも気持ち悪かったので、これでようやくすっきりしました。

せっかくランタイムライブラリのソースもあることやし、自分でちょっと追いかけてみたところすんなり問題となる箇所が見つかりました。

		// FUNCTION _Mbrtowc
inline int _Mbrtowc(wchar_t *_Wptr, const char *_Ptr, size_t _Count,
	_Mbstatet *_Pstate, const _Cvtvec *)
	{	// perform locale-specific mbrtowc
	return (_CSTD mbrtowc(_Wptr, _Ptr, _Count, (mbstate_t *)_Pstate));
	}

               :

		// FUNCTION _Wcrtomb
inline int _Wcrtomb(char *_Ptr, wchar_t _Char,
	_Mbstatet *_Pstate, const _Cvtvec *)
	{	// perform locale-specific wcrtomb
	return (_CSTD wcrtomb(_Ptr, _Char, (mbstate_t *)_Pstate));
	}

C:\Program Files\Borland\BDS\4.0\include\dinkumware の下にある xlocinfo からの抜粋です。*1
引数で渡されてきた locale の情報(const _Cvtvec* の箇所)を全く使わずに、C 関数の方の mbrtowc() や wcrtomb() を呼び出していますね。
C関数の方はグローバルに設定された locale に従うので、id:logion:20060209#p1 で書いた事実(先にグローバルな locale を設定したらうまく動いた)も納得できます。でも、せっかく locale オブジェクトを導入し、複数のロケールを同時に扱えるようにした C++ の locale において、この実装はマズいんとちゃうやろか…。
どうせ C 関数の方も Win32API の MultiByteToWideChar() や WideCharToMultiByte() を呼び出しているでしょうし、解決策としては C 関数を経由せず直接 Win32API を呼び出すように書き換えればよさそうです。(まあグローバルにセットする方法で今のところ不自由はしていませんので、やる予定はないですが…)

*1:include\dinkumware\ の下にあるので、結局の所ランタイムのソースは無関係でした。orz