当使用 _ENABLE_PER_THREAD_LOCALE 时,STL 对象使用 C 运行时库语言环境进行浮点转换?
C 运行时语言环境由 setlocale
设置。 标准 C++ 库 (STL) 区域设置由 std::locale
类设置,并且可以在单个 STL 对象(例如 std::istringstream 等)上设置。
函数 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
code> 允许在每个线程的基础上设置 C 运行时区域设置。
不幸的是,启用 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
的线程中的 STL 对象似乎正在使用 C 运行时区域设置。或者至少使用 C 运行时语言环境的小数点。
在没有 _ENABLE_PER_THREAD_LOCALE
的线程中,没有问题。
Paavo 在 2008 年提出了类似的问题,但没有答案:_configthreadlocale 和 localeconv
下面的代码显示了问题:
//Enable per thread locale in current thread
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
//Create istringstream object
std::istringstream LibraryStream;
//Create double object
double Value = 0;
//Create std::locale object with "C" locale ("." as decimal point)
std::locale StreamLoc("C");
//Set C Runtime locale to danish ("," as decimal point)
setlocale(LC_ALL, "danish");
//Set the "C" locale on the istringstream object
LibraryStream.imbue(StreamLoc);
//Get the locale of the istringstream object for test (returns "C" as expected)
std::locale NewStreamLoc = LibraryStream.getloc();
//Set floating point string with "C" locale decimal point in istringstream object
LibraryStream.str("60.258351");
//Convert the string to double
LibraryStream >> Value;
//Now the expected value of "Value" is 60.258351, but it is 60.000
//when debugging the conversion, I can see that "," is used as decimal point
有没有人经历过这个前?我做错了什么吗?有解决方案的建议吗?
提前致谢 /TEB
The C Runtime locale is set by setlocale
.
The Standard C++ Library (STL) locale is set by the std::locale
class and can be set on individual STL objects like std::istringstream etc.
The function _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
allows setting the C Runtime locale on a per thread basis.
Unfortunately it seems that STL objects in threads where _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
is enabled is using the C Runtime locale. Or at least using the decimal point of the C Runtime locale.
In threads without _ENABLE_PER_THREAD_LOCALE
there are no problems.
Something similar was asked by Paavo in 2008, but with no answers: _configthreadlocale and localeconv
The following code shows the problem:
//Enable per thread locale in current thread
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
//Create istringstream object
std::istringstream LibraryStream;
//Create double object
double Value = 0;
//Create std::locale object with "C" locale ("." as decimal point)
std::locale StreamLoc("C");
//Set C Runtime locale to danish ("," as decimal point)
setlocale(LC_ALL, "danish");
//Set the "C" locale on the istringstream object
LibraryStream.imbue(StreamLoc);
//Get the locale of the istringstream object for test (returns "C" as expected)
std::locale NewStreamLoc = LibraryStream.getloc();
//Set floating point string with "C" locale decimal point in istringstream object
LibraryStream.str("60.258351");
//Convert the string to double
LibraryStream >> Value;
//Now the expected value of "Value" is 60.258351, but it is 60.000
//when debugging the conversion, I can see that "," is used as decimal point
Have anyone experienced this before? Am I doing something wrong? Are there any suggestions for solutions?
Thanks in advance
/TEB
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于 C++ 标准库最近才获得有关线程的知识,因此这种明显的二分法并不令我感到惊讶。对不同场景中发生的情况进行了详尽的讨论(特定于 Microsoft,但作为一般背景似乎很有帮助)这里。
总之:
Since C++ Standard Library only recently gained knowledge of threads, this apparent dichotomy does not surprise me. There is an exhaustive discussion of what happens in different scenarios (Microsoft-specific, but seems to be helpful as general background) here.
In summary:
免责声明:我不是语言环境专家,因此这可能是错误的。
关于多线程和区域设置知识库文章指出:
您确实正在使用 C++ 标准库,因此在我看来您需要调用
locale::global()
。当我这样做时,返回值正如你所期望的那样。这是我的示例代码:Disclaimer: I am not an expert at locales, so this may be wrong.
On the Multithreading and Locales Knowlegde Base article it is noted:
You are indeed using the C++ Std Lib, so it seemed to me that you needed to call
locale::global()
. When I did this, the return value is as you expected. Here is my sample code:约翰·迪布林说得好。我已经测试过了,运算符>>值确实使用流中的区域设置,而不是全局区域设置。它通过以下示例进行了测试:
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE),已删除
locale::global(locale("danish"));,添加以设置全局 Std lib 区域设置
我猜到目前为止的结论是启用 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) 的线程中的 STL 对象确实使用 C 运行时区域设置。
可以通过使用 locale::global() 调用设置 Std lib 语言环境和 C 运行时语言环境来解决此问题。但由于 Std lib 区域设置不是线程安全的,并且不受 _ENABLE_PER_THREAD_LOCALE 的影响,因此我们仍然可以通过此解决方法遇到多线程问题。
Good point John Dibling. I have tested that and the operator>> Value does use the locale in the stream and not the global locale. It was tested by the example below:
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE), removed
locale::global(locale("danish"));, added to set the global Std lib locale
I guess the conclusion so far is that STL objects in threads where _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) is enabled is indeed using the C Runtime locale.
It is possible to work around this by setting both the Std lib locale and the C Runtime locale with the locale::global() call. But as Std lib locale is not thread safe and not affected by the _ENABLE_PER_THREAD_LOCALE, we can still run in to multithreading problems with this workaround.