C++ 微软实施的mbstowcs_是线程安全的吗?

C++ 微软实施的mbstowcs_是线程安全的吗?,c++,multithreading,c++11,visual-studio-2013,C++,Multithreading,C++11,Visual Studio 2013,在我的应用程序中,我需要多字节字符串到宽字符串的线程安全转换。为此,我使用了mbstowcs\u。我发现有一点值得注意,即一些mbstowcs\u实现不是线程安全的,但根本没有关于线程安全的内容 Microsoft实施的mbstowcs\u是线程安全的吗 有两种可能的方式使实现受到竞争条件的影响。首先,它可以依赖单个全局共享状态,其次,它必须查询全局语言环境 有一个mbsrtowcs_s函数,它接受一个显式的mbstate,根据设计,它不会有第一个问题。还有一个Microsoft特有的\u mb

在我的应用程序中,我需要多字节字符串到宽字符串的线程安全转换。为此,我使用了
mbstowcs\u
。我发现有一点值得注意,即一些
mbstowcs\u
实现不是线程安全的,但根本没有关于线程安全的内容


Microsoft实施的
mbstowcs\u
是线程安全的吗

有两种可能的方式使实现受到竞争条件的影响。首先,它可以依赖单个全局共享状态,其次,它必须查询全局语言环境

有一个mbsrtowcs_s函数,它接受一个显式的mbstate,根据设计,它不会有第一个问题。还有一个Microsoft特有的
\u mbstowcs\u s\l
函数,它接受一个显式的区域设置,从设计上看,这不会有第二个问题。有趣的是,没有
\u mbsrtowcs\u s\u l
,因为显然没有可能的线程问题是很难要求的

如果任何其他线程同时调用
setlocale
,则
mbsrtowcs\u s
的文档会显式调用争用条件,如Danh发布的链接所示。不幸的是,似乎没有关于转换状态是否存在竞争条件的明确文档

然而,微软传统上对单线程CRT和多线程CRT进行了区分,多线程版本的线程本地状态保存了内部返回或使用的CRT函数的所有静态,使得strtok之类的函数是线程安全的,尽管不是完全可重入的。这显然适用于
mbstwcs
及其变体。较新版本的VisualStudio甚至不再有单线程版本


虽然我在星期一上班之前不能检查,但我确信,<>代码> BMSTOWCSYSLL至少是完全线程安全的。< /P> < P>给出的问题被标记为C++是你的朋友

以下工作与:

  • VS2010+
  • GCC5+
如果MBCS字符串为UTF-8:
#包括
#包括
使用utf8converter=std::wstring\u convert;
std::wstring加宽(const std::string&to_加宽)
{
返回utf8converter{}.from_字节(to_加宽);
}
标准::字符串窄(常数标准::wstring&to_窄)
{
返回utf8converter{}.to_字节(to_狭窄);
}
如果字符串是其他语言环境(在线程上设置):
使用locale\u converter=std::wstring\u convert;
std::wstring加宽(const std::string&to_加宽)
{
返回区域设置\u转换器{}。从\u字节(到\u字节);
}
标准::字符串窄(常数标准::wstring&to_窄)
{
返回locale_converter{}.to_字节(to_狭窄);
}

据我所知,基于区域设置的工具也是线程安全的,因为它们在构建时会获取当前线程的区域设置方面的副本。考虑到区域是线程特定的,它本来就是线程安全的……/P>目前没有VS2013,但是IIRC仍然与CRT源代码一起航行。为什么这被标记为C++,这是关于C运行时函数的?在C++中有更好的方法可以做到安全和保证标准。safe@Mgetz如果OP写C++程序,问题就被标记了。这就是标签:定义解决方案集的约束。@ MGETZ:你能分享你的C++解决方案吗?是的,它是线程安全的。CRT中的全局变量,如本例中的mbstate_t变量,是线程局部变量。实际上,的MSDN说明中关于线程安全条件的措辞非常奇怪:
如果当前线程中没有函数调用setlocale,只要该函数正在执行且mbstate参数不是空指针。
它可以被视为当前(单)线程调用
mbsrtowcs\u
(使用非空
mbstate
参数),然后调用
setlocale
,然后再次调用
mbsrtowcs
。它没有说明另一个名为
setlocale
的线程在执行
mbsrtowcs\u s
@Sebastian:Thnx时的用法。为了总结您的答案,您是否建议将所有代码更新为
mbsrtowcs\u
在字符串转换中实现线程安全?目前我们正在使用
mbstowcs\u
。Thnx,我将尝试您的解决方案。我需要确保它不会导致性能问题。我从来没有遇到过它的问题,但我也从来没有把它放在一个非常热门的位置。但是对于99%的用例,如果没有潜在的问题,它应该是好的ter由于内联,在UTF8情况下没有跨DLL边界调用。
#include <locale>
#include <codecvt>


using utf8converter = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>;
std::wstring widen(const std::string &to_widen)
{
    return utf8converter{}.from_bytes(to_widen);
}

std::string narrow(const std::wstring &to_narrow)
{
    return utf8converter{}.to_bytes(to_narrow);
}
using locale_converter = std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>>;

std::wstring widen(const std::string &to_widen)
{
    return locale_converter{}.from_bytes(to_widen);
}

std::string narrow(const std::wstring &to_narrow)
{
    return locale_converter{}.to_bytes(to_narrow);
}