首页 > 解决方案 > thread_local unordered_map 加上 AccessibleObjectFromWindow 不在 WinXP 中运行

问题描述

我正在使用 VC++ 2015 编译以下程序。

#include <oleacc.h>
#include <unordered_map>

#pragma comment(lib,"User32.lib")
#pragma comment(lib,"Oleacc.lib")

thread_local std::unordered_map<int, int> something ;

int main( int argc, char* argv[] ){
    
    MessageBox(0, "Program started", "Test program", MB_SETFOREGROUND) ;
        
    IAccessible* test ;
    AccessibleObjectFromWindow(GetForegroundWindow(), OBJID_WINDOW, IID_IAccessible, (void**)&test) ;   
}

命令行:
cl test.cpp /EHsc /link /MACHINE:x86 /entry:mainCRTStartup /subsystem:windows,5.1

程序显示一个消息框并退出。它适用于除 Windows XP 之外的所有 Windows 版本,在这些版本中,双击程序图标时没有任何反应。

没有错误消息或任何表明程序失败的迹象。它什么也不做。它会在任务管理器中显示几分之一秒,然后消失。

必须存在以下两个元素才能使程序在 Win XP 中失败。

  1. thread_local unordered_map全局范围内的A。
  2. 打电话给AccessibleObjectFromWindow

如果我进行以下任何更改,该程序确实可以在 XP 中运行:

是否有任何命令行参数可以传递给编译器/链接器,以便程序在 WinXP 中运行?


更新:

如果我添加/MD到命令行(即使用操作系统中安装的运行时),WinXP可以成功运行程序。

这表明问题是 Windows XP 和 VS2015 嵌入到可执行文件中的 MSVC 运行时库之间存在某种不兼容(我也尝试使用 VS2019,但没有区别)。

我尝试通过 GUI 构建项目并选择Windows XP (v140_xp)作为平台工具集,但问题仍然存在。

我想我唯一的选择是更改unordered_mapmap. thread_local或者以某种方式摆脱。

标签: c++visual-c++comwindows-xpthread-local

解决方案


尝试添加/Zc:threadSafeInit-到编译器命令行。

来自VC++ 2015 的线程安全本地静态初始化

线程安全的静态局部变量在内部使用线程局部存储 (TLS) 以在静态已经初始化时提供高效执行。此功能的实现依赖于 Windows Vista 及更高版本操作系统中的 Windows 操作系统支持功能。 Windows XP、Windows Server 2003 和较早的操作系统没有此支持, 因此它们无法获得效率优势。这些操作系统对可以加载的 TLS 部分的数量也有下限。超过 TLS 部分限制可能会导致崩溃。如果这是您的代码中的问题,尤其 是必须在旧操作系统上运行的代码中,请使用 /Zc:threadSafeInit- 禁用线程安全初始化代码。


推荐阅读