最近,Microsoft Visual Studio 2015编译器最终符合C ++标准要求,以生成用于函数局部静态函数的线程安全代码。在大多数情况下,这工作正常,但是在Windows XP上我遇到了以下3条指令导致崩溃的情况:

mov     eax,dword ptr fs:[0000002Ch]
mov     ecx,dword ptr [MyModule!_tls_index (102eea44)]
mov     ecx,dword ptr [eax+ecx*4]


显然,编译器似乎首先进入当前线程的TLS插槽,以实现线程安全。每个文档都应该使用fs:2Ch导致TLS阵列。但是,在Windows XP上,似乎未设置fs:2Ch。这为我返回了0,所以下一条指令也是如此(_tls_index也是0。)这导致第三条指令因访问无效内存而崩溃。

有人知道为什么可能无法设置fs:2Ch在Windows XP上?函数局部静态函数在我们的所有代码中都使用,我无法想象没有其他人会遇到这种情况。

#1 楼

如果您的模块是一个由可执行文件动态加载的DLL,则不会在Windows XP上为该DLL初始化线程本地存储。

引用“我的“终极”反调试参考”部分4,第25页:

”在Windows Vista和更高版本上,动态加载的DLL也支持线程本地存储。这与现有的可移植可执行格式文档直接矛盾,该文档指出“静态声明的TLS数据对象...只能在静态加载的图像文件中使用。这个事实使在DLL中使用静态线程本地存储数据变得不可靠,除非您知道该DLL或与其静态链接的任何内容都不会通过LoadLibrary API函数动态加载。”

评论


彼得:非常感谢!这确实是一个巨大的资源。我希望可以在Google上轻松找到它。 FWIW,一个好心人也把这个发送给我:connect.microsoft.com/VisualStudio/Feedback/Details/1941836现在,事情变得更加清晰了。

–永远学习
16 Dec 16 '18:08



有关此问题的更多历史记录:nynaeve.net/?p=189

–伊戈尔·斯科钦斯基♦
16 Dec 16'在18:28

有什么想法如何解决以下问题?我有.NET可执行文件,可以从本机DLL(P / Invoke)调用函数。 DLL由LoadLibrary加载,我遇到了这个问题(因为DLL具有静态变量)。我尝试以某种方式将本机DLL添加到.NET可执行文件(PE)的DLL导入表中,但此后我无法运行该可执行文件...不确定这是否真的有帮助。

–Pupsik
17-10-29在13:07

@Pupsik,请创建一个新问题来讨论您的问题。评论部分不适用于此目的。

–彼得·弗里
17年11月4日在3:00