日本語ロケールでassertion failedになる件
昨日の日本語ロケールだとBoost.Xpressiveがassert落ちする件を調べてみました。
落ちるのはココです。
template<typename Char> struct cpp_regex_traits_base<Char, 1> { protected: void imbue(std::locale const &loc) { int i = 0; Char allchars[UCHAR_MAX + 1]; for(i = 0; i <= UCHAR_MAX; ++i) { allchars[i] = static_cast<Char>(i); } std::ctype<Char> const &ct = BOOST_USE_FACET(std::ctype<Char>, loc); std::ctype_base::mask tmp[UCHAR_MAX + 1]; ct.is(allchars, allchars + UCHAR_MAX + 1, tmp); for(i = 0; i <= UCHAR_MAX; ++i) { this->masks_[i] = static_cast<umask_t>(tmp[i]); BOOST_ASSERT(0 == (this->masks_[i] & non_std_ctype_masks)); }boost/xpressive/traits/cpp_regex_traits.hpp
ここでは、ロケールからctypeを取ってきて、そこから文字タイプのマスクを全文字分取得しています。
BOOST_ASSERT()の箇所はBoost.Xpressive用の追加フラグ領域が未使用であることをチェックしています。
追加フラグはstd::ctype_base::maskの各要素で使われていないビットを上位ビットから順に割り当ててあります。
VC++で使われているDinkumwareの標準ライブラリだと、このマスクの値はGetStringTypeA()で取得できるものをそのまま使っていて、これにstd::ctype_base::maskにないビットも含まれているのが原因です。
どうもマルチバイト文字のリーディングバイトだと、このマスクが不正な文字として0x8000になるようです。
ということで報告してきました。
http://svn.boost.org/trac/boost/ticket/1625
多分、DinkumwareとWindowsの組み合わせならVC++以外でも発生します。
Borlandのも同じでした。
(2/9: 追記)
上記のバグは修正されました。
http://svn.boost.org/trac/boost/changeset/43177