簡體   English   中英

是setlocale線程安全的功能嗎?

[英]Is setlocale thread-safe function?

我需要在線程中更改區域設置以正確解析帶有strtod()的double,我正在使用setlocale()(C ++)。 它是線程安全的嗎?

更新:另一個問題。 當我在main()函數中調用setlocale()時,它不會更深入地影響其他例程。 為什么??? 有很多代碼,所以編寫塊有問題。

在C ++ 11標准中,線程現在是該語言的受支持部分。 該標准明確指出setlocale()調用引入了對setlocale()的其他調用的數據爭用,或者調用受當前C語言環境影響的函數,包括strtod()。 locale :: global()函數被認為是行為 - 如果它調用了setlocale(),所以它也可以引入數據競爭(如下所述)。

在使用glibc的Linux上, MT-unsafe(const:locale env)使線程與非NULL參數同時調用setlocale()並調用可能使用全局語言環境的任何其他函數(數據競爭,因此在C11中未定義的行為) 。 建議使用uselocale()代替MT-safe並僅更改調用線程的語言環境。 在使用C ++代碼中的libstdc ++的Linux上,您應該避免使用locale :: global(進程范圍更改)並為線程的使用創建一個語言環境(locale :: global出於MT安全性的原因與C運行時相同)。 鑒於您的目標是使用strtod(C API),您應該使用uselocale()。

在使用glibc的Linux上,setlocale()函數本身是MT不安全的,除非你滿足2個嚴格的標准,並且根據POSIX的要求改變整個過程的語言環境。 新的Linux手冊頁( Red Hat和Fujitsu的一部分用於為所有API指定MT安全符號 )將setlocale()標記為“MT-Unsafe const:locale env”,這意味着setlocale是您保留的MT安全IFF語言環境常量(通過不修改它,只是通過傳遞NULL來查詢它),並且如果保持語言環境和環境不變(以避免在參數為“”時更改語言環境)。 在使用glibc的Linux上,如果你想只改變調用線程的語言環境,你應該使用uselocale(),因為這是MT安全的,並且不以任何方式依賴你的環境,strtod將使用線程的語言環境。 類似地,所有實現POSIX的系統都應該提供uselocale()以用於線程上下文(MT-safe)。

OS X實現了uselocale(),因此您可以使用它。

在Windows上使用_configthreadlocale來更改setlocale()是否對整個進程或線程進行操作(將其轉換為您需要的uselocale),但是對於C ++代碼,您應該再次使用locale類的實例並避免使用locale :: global

對setlocale()的調用可能是也可能不是線程安全的,但是語言環境設置本身是按進程而不是每個線程。 這意味着即使您的setlocale()是線程安全的,或者您使用互斥鎖來保護自己,更改仍將更新所有線程的當前區域設置。

但是有一個每線程的替代方案:uselocale()。

#include <xlocale.h>

locale_t loc = newlocale(LC_ALL_MASK, "nl_NL", NULL);
uselocale(loc);
freelocale(loc)
// Do your thing

語言環境在內部使用引用計數,這就是為什么在使用newlocale()激活它之后釋放它是安全的。

您需要查閱文檔以了解您正在使用的任何實現。 C ++目前沒有指定任何關於線程的內容,所以它歸結為實現(你還沒有告訴我們)。

例如,我的s​​etlocale的Linux手冊頁有以下代碼段:

該字符串可以在靜態存儲中分配。

這並不是絕對表明它的線程不安全但我會非常謹慎。 可能是因為使用NULL調用(即查詢)將是線程安全的,但只要你有一個線程修改它,全盤皆輸。

可能最安全的做法(假設它不是線程安全的)將保護所有使用互斥鎖的setlocale調用,並具有一個特殊的函數來格式化你的數字:

claim mutex
curr = setlocale to specific value
format number to string
setlocale to curr
release mutex
return string

對於C ++ 98,它取決於編譯器以及您選擇的運行時庫以及線程安全的確切含義。

例如,對於MSVC和多線程運行時,從setlocale本身來看,你應該是安全的。 但我認為你不會得到一個每線程的語言環境。 setlocale用於全局區域設置,而不是每線程區域設置。

C ++ 98不涉及線程(或者,就此而言,動態庫)。

C語言支持本地線程。 請閱讀http://msdn.microsoft.com/en-us/library/ms235302.aspx 主要方法是:_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)

解決原始問題的第二部分:

setlocale函數位於C庫中(由標准頭<clocale>在C ++環境中定義),其使用僅影響C庫例程。 你在問題的第一部分提到了C ++,所以我想知道你是否期望C ++例程注意到用setlocale做的語言環境更改。 我的經驗表明他們不會。

在C ++中處理語言環境信息的正確方法是由標准C ++標頭<locale>指定的庫定義的。 該庫以與C ++ I / O操作兼容的方式提供對區域設置信息的控制。 例如,您可以創建具有某些特征的std::locale對象,然后將std::filebuf與該對象一起使用,以便I / O操作遵循這些特性。

如果您在混合C / C ++環境中運行,請使用std::locale::global() - 使用正確的參數類型,它還將C全局語言環境設置為使用LC_ALL調用C庫函數setlocale 這將使C和C ++庫功能保持同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM