好吧。对于 Windows Vista 及更高版本,正如 James McNellis 所说 - 我们可以使用FlsCallback。
对于 DLL,我们可以只使用 DllMain,如果原因参数等于 DLL_THREAD_DETACH,我们会进行清理。另一种方法可能是使用 _pRawDllMain,它就像另一个 DllMain,您可以从boost source中找到它。
对于 EXE,我们可以使用 TLS 回调,请查看
此处和此处,当然还有boost source。实际上,它可以在 Windows XP 上运行,但我发现优化可能会使其无效,所以要小心优化,或者明确引用回调函数的指针。
将下面的代码保存到tls.cpp并添加到你的项目中,不管是exe还是dll都可以。请注意,对于 Windows Vista 及更高版本上的 DLL,onThreadExit 函数可能会被调用两次——一次来自 dll_callback,一次来自 tls_callback。
#include <windows.h>
extern void onThreadExit();
static void NTAPI tls_callback(PVOID, DWORD reason, PVOID)
{
if (reason == DLL_THREAD_DETACH) {
onThreadExit();
}
}
static BOOL WINAPI dll_callback(LPVOID, DWORD reason, LPVOID)
{
if (reason == DLL_THREAD_DETACH) {
onThreadExit();
}
return TRUE;
}
#pragma section(".CRT$XLY",long,read)
extern "C" __declspec(allocate(".CRT$XLY")) PIMAGE_TLS_CALLBACK _xl_y = tls_callback;
extern "C"
{
extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID) = &dll_callback;
}
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma comment(linker, "/INCLUDE:__xl_y")
如果你觉得它晦涩难懂,请使用 boost 的at_thread_exit,复杂性被隐藏了。事实上,上面的代码是 boost tls 的简化版本。如果您不想使用 boost,在 Windows 系统上这是一个替代方案。
或者,更通用的方式:thread_local。