Windows 10下TLS回调实现异常:仅单个回调执行问题咨询
TLS回调函数未全部执行的问题分析与解决
修正后的代码
#include <Windows.h> #include <cstdio> __declspec(thread) int a; __declspec(thread) int b; void NTAPI on_tls_callback(void* dll, DWORD reason, void* reserved) { a = 543; // 0x21F //MessageBox(nullptr, L"In TLS", L"In TLS", MB_OK); printf("a in on_tls_callback function: %d\n", a); } void NTAPI on_tls_callback_test(void* dll, DWORD reason, void* reserved) { b = 10; // 0xA //MessageBox(nullptr, L"Another In TLS", L"Another In TLS", MB_OK); printf("b in on_tls_callback_test function: %d\n", b); } #pragma comment (linker, "/INCLUDE:__tls_used") // 修正回调段的链接器指令 #pragma data_seg(".CRT$XLA") #pragma comment (linker, "/INCLUDE:_xl_a") // 修正符号名:去掉多余的下划线 EXTERN_C __declspec(allocate(".CRT$XLA")) PIMAGE_TLS_CALLBACK _xl_a = (PIMAGE_TLS_CALLBACK)on_tls_callback_test; #pragma data_seg() #pragma data_seg(".CRT$XLX") #pragma comment (linker, "/INCLUDE:_xl_x") // 同步修正此处符号名 EXTERN_C __declspec(allocate(".CRT$XLX")) PIMAGE_TLS_CALLBACK _xl_x = (PIMAGE_TLS_CALLBACK)on_tls_callback; #pragma data_seg() __declspec(thread) int c = 9; int main() { printf("a in main: %d\n", a); printf("b in main: %d\n", b); c = 15; printf("c in main: %d\n", c); //MessageBox(nullptr, L"In Main", L"In Main", MB_OK); printf("end main !!!\n"); getchar(); return 0; }
问题原因
你的代码核心错误是链接器包含的符号名与实际变量名不匹配:
- 你定义的回调变量是
_xl_a(单下划线前缀),但链接器指令写的是/INCLUDE:__xl_a(双下划线前缀),导致链接器无法识别该符号,最终.CRT$XLA段中的on_tls_callback_test回调没有被加入到系统的TLS回调数组中,程序启动时不会执行这个回调。 - Windows TLS回调的机制是:链接器会自动合并所有位于
.CRT$XL*(后缀为A-Z字母)段中的PIMAGE_TLS_CALLBACK变量为一个数组,程序加载时系统会遍历该数组依次执行回调。如果变量因符号未被引用且未强制包含被链接器丢弃,对应的回调就不会触发。
变量b值为0的原因
由于on_tls_callback_test从未执行,b = 10;的赋值操作没有运行。而__declspec(thread)修饰的全局变量,若未显式初始化,会被默认初始化为0,因此main函数中读取到的b值为0。
修正后预期输出
b in on_tls_callback_test function: 10 a in on_tls_callback function: 543 a in main: 543 b in main: 10 c in main: 15 end main !!!
注:TLS回调的执行顺序由段名后缀字母决定,.CRT$XLA的后缀A在.CRT$XLX的X之前,因此on_tls_callback_test会先执行
内容的提问来源于stack exchange,提问作者tu nguyen
相关产品推荐
相关产品推荐

