mbstowcs_s的Microsoft实现是否是线程安全的

时间:2015-12-11 11:12:20

标签: c++ multithreading c++11 visual-studio-2013

在我的应用程序中,我需要将多字节字符串的线程安全转换为宽字符串。我为此目的使用mbstowcs_sHere我发现一些mbstowcs_s实现不是线程安全的,但MSDN没有关于线程安全的说明。

Microsoft mbstowcs_s线程的实现安全吗?

2 个答案:

答案 0 :(得分:1)

实施可能有两种可能的竞争条件。首先,它可以依赖单个全局共享mbstate,其次,它必须查询全局区域设置。

有一个mbsrtowcs_s函数接受一个显式的mbstate,它在设计上不会有第一个问题。还有一个特定于Microsoft的_mbstowcs_s_l函数,它接受一个显式的语言环境,根据设计它不会有第二个问题。有趣的是,没有_mbsrtowcs_s_l,因为显然没有可能的线程问题太多了。

如果任何其他线程同时调用mbsrtowcs_ssetlocale的文档会显式调出竞争条件,如Danh发布的链接所示。遗憾的是,似乎没有关于转换状态是否存在竞争条件的明确文档。

然而,微软传统上一直区分单线程和多线程CRT,其中多线程版本具有线程本地状态,包含所有CRT功能'在内部返回或使用的静态函数,使函数像strtok线程安全,但不完全可重入。按理说这也适用于mbstwcs及其变体。较新版本的Visual Studio甚至不再具有单线程版本。

因此,虽然在周一回到工作岗位之前我无法检查,但我确信_mbstowcs_s_l至少是完全线程安全的。

答案 1 :(得分:1)

鉴于此问题被标记为C ++ <codecvt>是您的朋友

以下工作:

  • VS2010 +
  • GCC5 +

如果您的MBCS字符串是UTF-8:

#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);
}

据我所知,基于语言环境的语言库也是线程安全的,因为它们在构造时会获取当前线程的语言环境构面的副本。鉴于locale是特定于线程的,无论如何它本身就是线程安全的......