libstdc++ のロケール問題

スレを勃てるまでもないC/C++の質問はここで 7


441 :デフォルトの名無しさん [↓] :2009/02/08(日) 01:48:07
未だに GCC 4.0.1 を使ってるんだけど、
setlocale すると必ず死ぬし、まともにワイド文字列も扱えない様子。
4.3.3 にしたらこのあたり改善されてるの?


443 :デフォルトの名無しさん [↓] :2009/02/08(日) 03:30:15
ワイド文字列の日本語を出力しようとすると ? になんだが、
そう言われると確かに g++ の問題ではないかもしれない。
環境は MacOSX 10.4.11 だけど、ターミナルの環境設定が何かまずいのかも?

でも、setlocale で死ぬのは流石に関係ないと思いたい。
というか、setlocale じゃなくて std::locale::global だった。すまん。

std::locale::global(std::locale("japanese"));

terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
Abort trap


444 :デフォルトの名無しさん [↓] :2009/02/08(日) 04:08:52
>443
locale 文字列で "japanese" が通るのは VC じゃないのか?
"" か "ja_JP.UTF-8" とかでどうだ?


450 :デフォルトの名無しさん [↓] :2009/02/08(日) 12:17:24
>>444
"" でも死ぬ。


451 :デフォルトの名無しさん [↓] :2009/02/08(日) 12:22:25
"ja_JP.UTF-8" でも死んだ。
Mac で最新の GCC 使ってる人がいれば、
このあたり大丈夫かどうか教えてもらえれば助かります。
GCC 更新するの時間かかるし、
それで効果無かったら泣けるしね・・・。


455 :デフォルトの名無しさん [↓] :2009/02/08(日) 14:19:39
>>451
GCC4.3.2 でも死ぬ。
locale -a にある全てのロケールを試したけど、C と POSIX 以外通らない。
なんでこんなに腐ってるんだ。


456 :デフォルトの名無しさん [↓] :2009/02/08(日) 14:20:55
>>455
おお、ありがとうございます。
やはりGCCロケール未対応と考えた方が良さそうですな・・・。

http://pc11.2ch.net/test/read.cgi/tech/1232983248/


確かに俺の環境でも落ちる。そこで、libstdc++ を調べてみた。
gcc-4.3.3/libstdc++-v3/configure を見ると、--enable-clocale=xxx を与えないと、OS が darwin* | freebsd* の場合

config/locale/generic/c_locale.h
config/locale/generic/c_locale.cc
config/locale/generic/codecvt_members.cc
config/locale/generic/collate_members.cc
config/locale/darwin/ctype_members.cc
config/locale/generic/messages_members.h
config/locale/generic/messages_members.cc
config/locale/generic/monetary_members.cc
config/locale/generic/numeric_members.cc
config/locale/generic/time_members.h
config/locale/generic/time_members.cc
config/locale/generic/c++locale_internal.h

これらのコードが使われるっぽい。
ってか、FreeBSD と同じでいいんだろうか。。。


んで、config/locale/generic/c_locale.cc を見てみる。

void
locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 
          __c_locale)
{
  // Currently, the generic model only supports the "C" locale.
  // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
  __cloc = NULL;
  if (strcmp(__s, "C"))
    __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
        "name not valid"));
}

これはひどい。C しか通らないわけだ。
一方、--enable-clocale=gnu の場合に使われる config/locale/gnu/c_locale.cc は

void
locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 
          __c_locale __old)
{
  __cloc = __newlocale(1 << LC_ALL, __s, __old);
  if (!__cloc)
    {   
// This named locale is not supported by the underlying OS.
__throw_runtime_error(__N("locale::facet::_S_create_c_locale "
          "name not valid"));
    }   
}

ちゃんと処理している。
その他、gnu では __duplocale, __duplocale, __freelocale, __uselocale を使っていた。
darwin の libc にも newlocale, duplocale, freelocale, uselocale があるんだけどなぁ。。。
また、config/locale/darwin/ctype_members.cc では do_touuper, do_lower 関数内で towupper, towlower を呼んでいるが、
config/locale/gnu/ctype_members.cc では towupper_l, towlower_l を呼んでいる。
さらに、config/locale/generic/codecvt_members.cc では do_in, do_length 関数内で mbrtowc を、do_out 関数内で wcstomb を呼んで頑張っているが、
config/locale/gnu/codecvt_members.cc では mbsnrtowcs, wcsnrtombs を呼んでいる。
darwin の libc にもそれらがあるんだけどなぁ。。。


これら xlocale 系の関数が使われていない理由は何だろう?以前の darwin の libc に無かったのか?
xlocale(3) の man page を見ると日付が March 11, 2005、mbsnrtowcs, wcsnrtombs のは July 21, 2004 になってるんだけど。
generic に加えるのは無理なのかもしれないけど、darwin にはちゃんと加えてほしいなぁ。