在我的应用程序中,我需要将多字节字符串的线程安全转换为宽字符串。我为此目的使用mbstowcs_s
。 Here我发现一些mbstowcs_s
实现不是线程安全的,但MSDN没有关于线程安全的说明。
Microsoft mbstowcs_s
线程的实现安全吗?
答案 0 :(得分:1)
实施可能有两种可能的竞争条件。首先,它可以依赖单个全局共享mbstate,其次,它必须查询全局区域设置。
有一个mbsrtowcs_s
函数接受一个显式的mbstate,它在设计上不会有第一个问题。还有一个特定于Microsoft的_mbstowcs_s_l
函数,它接受一个显式的语言环境,根据设计它不会有第二个问题。有趣的是,没有_mbsrtowcs_s_l
,因为显然没有可能的线程问题太多了。
如果任何其他线程同时调用mbsrtowcs_s
,setlocale
的文档会显式调出竞争条件,如Danh发布的链接所示。遗憾的是,似乎没有关于转换状态是否存在竞争条件的明确文档。
然而,微软传统上一直区分单线程和多线程CRT,其中多线程版本具有线程本地状态,包含所有CRT功能'在内部返回或使用的静态函数,使函数像strtok线程安全,但不完全可重入。按理说这也适用于mbstwcs
及其变体。较新版本的Visual Studio甚至不再具有单线程版本。
因此,虽然在周一回到工作岗位之前我无法检查,但我确信_mbstowcs_s_l
至少是完全线程安全的。
答案 1 :(得分:1)
鉴于此问题被标记为C ++ <codecvt>
是您的朋友
以下工作:
#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是特定于线程的,无论如何它本身就是线程安全的......