TLS 回调,其中调用sprintf_s导致崩溃



这是我的代码:

#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:p_tls_callback1")
#pragma const_seg(push)
#pragma const_seg(".CRT$XLAAA")
EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1 = tls_start_protect;
#pragma const_seg(pop)

而以下一段代码由tls_start_protect直接调用。

char buf[10];
sprintf_s(buf, 10, "hellon");

它崩溃了。

0:000> k
# Child-SP          RetAddr           Call Site
00 0000007c`e676eb58 00007ff6`e3b04829 AGTtest!__crtFlsGetValue+0x10 [f:ddvctoolscrtcrtw32miscwinapisupp.c @ 422] 
01 0000007c`e676eb60 00007ff6`e3b047f3 AGTtest!_getptd_noexit+0x1d [f:ddvctoolscrtcrtw32startuptidtable.c @ 277] 
02 0000007c`e676eb90 00007ff6`e3b03737 AGTtest!_getptd+0xb [f:ddvctoolscrtcrtw32startuptidtable.c @ 337] 
03 0000007c`e676ebc0 00007ff6`e3b06030 AGTtest!_LocaleUpdate::_LocaleUpdate+0x1b [f:ddvctoolscrtcrtw32hsetlocal.h @ 248] 
04 0000007c`e676ebf0 00007ff6`e3b02816 AGTtest!_output_s_l+0x6c [f:ddvctoolscrtcrtw32stdiooutput.c @ 1028] 
05 0000007c`e676ef10 00007ff6`e3b028a8 AGTtest!_vsnprintf_helper+0x92 [f:ddvctoolscrtcrtw32stdiovsprintf.c @ 140] 
06 0000007c`e676ef80 00007ff6`e3b025a3 AGTtest!_vsprintf_s_l+0x3c [f:ddvctoolscrtcrtw32stdiovsprintf.c @ 237] 
07 0000007c`e676efc0 00007ff6`e3b0112f AGTtest!sprintf_s+0x1f [f:ddvctoolscrtcrtw32stdiosprintf.c @ 216] 
08 0000007c`e676f000 00007ffb`bd6a52c8 AGTtest!tls_start_protect+0x1f [d:reposantidebugagttls_callback.c @ 83] 
09 0000007c`e676f040 00007ffb`bd6a1577 ntdll!LdrpCallInitRoutine+0x4c
0a 0000007c`e676f0a0 00007ffb`bd7201cd ntdll!LdrpCallTlsInitializers+0x93
0b 0000007c`e676f120 00007ffb`bd75166d ntdll!LdrpInitializeProcess+0x1c99
0c 0000007c`e676f510 00007ffb`bd706d5e ntdll!_LdrpInitialize+0x4a8b9
0d 0000007c`e676f590 00000000`00000000 ntdll!LdrInitializeThunk+0xe

同样,_vscprintf(format, args)家族也在__crtFlsGetValue崩溃。

我想知道现在打电话给printf家人还为时过早,在此之前,初始化还没有完成。我所知道的是TLS回调(仅DLL_PROCESS_ATTACH(是在'ntdll'之后执行的!Ldr*' 加载所有依赖模块,并在"EOP"之前加载。

问题

  • 关于_vscprintf初始化的任何细节,是在某些CPP构造函数的代码中由"CRT"完成的吗???

  • TLS 回调的任何其他限制???

  • 如果我确实需要在 TLS 回调中调用_vscprintf,如何操作?(不知何故,我只想在main之前打印(

使用静态链接 CRT - 这在堆栈跟踪中可见。 在调用 EXE 入口点后初始化的 EXE 中的静态链接 CRT。 但是 TLS 回调DLL_PROCESS_ATACH

在 EXE 入口点之前调用。 在这种情况下,您的静态CRT 尚未初始化,对此 CRT 代码的任何调用都可能崩溃。 解决方案 - 在单独的 DLL 中使用动态链接的 CRT - 在这种情况下,它将在 TLS 回调之前初始化

最新更新