>ostream
运算符<<
使用num_put::put()
进行数字格式设置。我正在尝试遵循代码。我将链接到OSX文件,但类似的文件出现在我查看的其他一些系统上。在我看来,num_put::put()
称num_put::do_put()
,它调用
num_put::_M_insert_float()
,其中calls __convert_from_v()
:
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/c++locale.h
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.tcc
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.h
__convert_from_v()
检查当前的全局区域设置,如果它与"C"不同,则调用setlocale()
将全局区域设置设置为"C",然后使用 vsnprintf()
设置数字格式,然后再次调用setlocale()
以恢复到旧的区域设置。
由于setlocale()
会影响所有线程ostream
,因此在将全局区域设置设置为"C"以外的多线程应用程序中,使用浮点数调用运算符<<
似乎是不安全的。但那会很奇怪,所以我错过了什么?谢谢!
最新草案(N3936)特别警告
:§ 18.10
6 调用 setlocale 函数可能会引入数据竞争 对 setlocale 函数的其他调用或对以下函数的调用 受当前 C 语言环境的影响。实现应行为 好像除了 locale::global() 之外没有库函数调用 设置区域设置函数。
较新版本的 GCC 将调用限制为 LC_NUMERIC
而不是 LC_ALL
,如果您使用 glibc> 2.2,则实现通过调用仅修改当前线程的 uselocale
完全避免了这个问题(我猜在 OSX 上对你没有多大用处......
编辑:我更好地查看了源代码
尽管如果从另一个线程调用依赖于 C 语言环境的函数,而__convert_from_v
或其他函数修改 C 区域设置,则通用区域设置模型可能会出现问题,但通用区域设置模型唯一支持的区域设置是 "C"
(这是启动期间设置的区域设置),因此除非将对其他区域设置的支持添加到通用模型中,否则这不是问题。
唯一可能成为问题的情况是,如果 gcc 是使用 gnu 语言环境模型构建的,并且 glibc 是 <= 2.2,这在 OSX 上不会发生。