Windows XP 下 CAtlStringMgr::GetInstance 崩溃
Posted
技术标签:
【中文标题】Windows XP 下 CAtlStringMgr::GetInstance 崩溃【英文标题】:Crash in CAtlStringMgr::GetInstance under Windows XP 【发布时间】:2015-12-14 12:05:38 【问题描述】:我编写了一个创建 ATL CString 对象的 DLL。我使用“Visual Studio 2015 - Windows XP (v140_xp)”平台工具集通过 Visual Studio 2015 编译它。 DLL 是使用 LoadLibrary/GetProcAddress 加载的。
在 Windows XP 下分配字符串对象时,它会在 CAtlStringMrg::GetInstance 中崩溃。相同的应用程序在 Windows Vista 及更高版本上运行良好。
这是反汇编:
static IAtlStringMgr* GetInstance()
#pragma warning(push)
#pragma warning(disable: 4640)
static CWin32Heap strHeap( ::GetProcessHeap() );
1003B100 mov eax,dword ptr fs:[0000002Ch]
1003B106 mov ecx,dword ptr [__tls_index (101B46C8h)]
1003B10C push esi
*** This is the instruction that causes the crash. eax and ecx are zero. ***
1003B10D mov esi,dword ptr [eax+ecx*4]
如您所见,代码引用了 __tls_index,因此它使用线程本地存储。当我使用旧的 Visual Studio 2013 编译我的项目时,dumpbin 还显示了一个不存在的 .tls 部分。
动态加载 DLL 时,Windows XP 不支持线程本地存储。这就解释了为什么上面的代码会崩溃。
但是,我无法弄清楚为什么要使用线程本地存储。我在 ATL 源代码中的任何地方都找不到 __declspec(thread)。
我正在寻找修复/解决方法(除了从 VS2015 回到 VS2013)。
该问题已报告给 Microsoft,但他们尚未评论/修复它:https://connect.microsoft.com/VisualStudio/feedback/details/1635157/crash-in-catlstringmrg-getinstance-under-windows-xp
【问题讨论】:
【参考方案1】:感谢 David 为我指明了正确的方向。这是解决方法:
属性 -> C/C++ -> 命令行 -> 添加“/Zc:threadSafeInit-”
相关文件:
https://connect.microsoft.com/VisualStudio/feedback/details/1715018/dll-usage-of-thread-safe-magic-statics-may-crash-on-windows-xp
Access violation on static initialization
https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics
https://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx
【讨论】:
"threadSafeInit-" 应该是使用 Windows XP 工具集构建的 DLL 的默认值。 哇,非常感谢!它非常神秘,似乎很容易......解决方法(至少感谢这个,MS) connect.microsoft.com 链接现在已损坏。 official Zc threadSafeInit documentation 中所述的 Windows XP 建议。以上是关于Windows XP 下 CAtlStringMgr::GetInstance 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
OpenFileDialog 在 Windows XP 下崩溃,但在 Windows 7 下不崩溃
windows xp下如何监控windows服务的状态变化?
Windows XP 下 CAtlStringMgr::GetInstance 崩溃