我發現MSDN中有關線程本地存儲初始值的矛盾。 This page說:Windows的線程本地存儲是否初始化值?
當創建線程時,系統爲TLS分配一個LPVOID值的數組,這些值初始化爲NULL。
這使我相信,如果我從一個從未爲同一索引調用過TlsSetValue的線程調用TlsGetValue,那麼我應該得到一個空指針。
This page,但是,說:
它是由程序員來保證......這個線程調用TlsGetValue前調用TlsSetValue。
這表明你不能依賴從TlsGetValue返回的值,除非你確定它已經用TlsSetValue明確初始化。
存儲在TLS時隙的數據可以具有0的值,因爲它仍然有它的初始值,或因爲該線程:
然而同時second page通過也說增強了初始化到空行爲所謂以0
所以我有兩個聲明說,該數據被初始化爲空(或0),一個說我必須讀值之前明確初始化它的TlsSetValue功能。在實驗上,這些值似乎被自動初始化爲空指針,但我無法知道我是否幸運,以及這是否總是如此。
我試圖避免使用DLL只是分配在DLL_THREAD_ATTACH。我想做一些懶惰的分配:
LPVOID pMyData = ::TlsGetValue(g_index);
if (pMyData == nullptr) {
pMyData = /* some allocation and initialization*/;
// bail out if allocation or initialization failed
::TlsSetValue(g_index, pMyData);
}
DoSomethingWith(pMyData);
這是一個可靠和安全的模式?或者,在我嘗試閱讀之前,是否必須明確初始化每個線程中的插槽?
更新:該文件還說,TlsAlloc zeros out the slots for the allocated index。因此,以前是否有一個插槽先前被該程序的另一部分使用似乎無關緊要。
不錯的推理,但事實證明TlsAlloc會重新初始化插槽爲零,因此組件B將返回0而不是組件A留下的垃圾值。我已經添加了一個更詳細的答案。 –
@Adrian它重新初始化當前線程的插槽。我相信其他線程仍然被擰緊。 [更新:其他線程確實沒有擰。他們在TlsFree時間被清零。] –
感謝您的額外期待。我也玩過足夠的東西,看到他們重新初始化了TlsFree,但我還沒有檢查過其他線程。 –