thread_local unordered_map 加上 AccessibleObjectFromWindow 不在 WinXP 中运行
Posted
技术标签:
【中文标题】thread_local unordered_map 加上 AccessibleObjectFromWindow 不在 WinXP 中运行【英文标题】:thread_local unordered_map plus AccessibleObjectFromWindow doesn't run in WinXP 【发布时间】:2020-07-02 00:32:50 【问题描述】:我正在使用 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 中失败。
-
一个
thread_local
unordered_map
在全局范围内。
致电AccessibleObjectFromWindow
如果我进行以下任何更改,该程序确实可以在 XP 中运行:
将unordered_map
更改为std::map
删除 thread_local
关键字
将thread_local
变量移入main
删除对AccessibleObjectFromWindow
的调用
是否有任何命令行参数可以传递给编译器/链接器,以便程序在 WinXP 中运行?
更新:
如果我在命令行中添加/MD
(即使用操作系统中安装的运行时),WinXP可以成功运行程序。
这表明问题是 Windows XP 和 VS2015 嵌入到可执行文件中的 MSVC 运行时库之间存在某种不兼容(我也尝试过 VS2019,但没有任何区别)。
我尝试通过 GUI 构建项目并选择 Windows XP (v140_xp) 作为平台工具集,但问题仍然存在。
我想我唯一的选择是将unordered_map
更改为map
。或者以某种方式摆脱thread_local
。
【问题讨论】:
你还没有初始化COM。 @RichardCritten,初始化 COM 没有区别,因为main
函数一开始就不会被调用。
这能回答你的问题吗? How to target Windows XP in Microsoft Visual Studio C++
【参考方案1】:
尝试将/Zc:threadSafeInit-
添加到编译器命令行。
来自Thread-safe Local Static Initialization for VC++ 2015:
线程安全的静态局部变量在内部使用线程局部存储 (TLS) 以在静态已经初始化时提供高效执行。此功能的实现依赖于 Windows Vista 及更高版本操作系统中的 Windows 操作系统支持功能。 Windows XP、Windows Server 2003 和更早的操作系统不支持此功能, 所以他们没有获得效率优势。这些操作系统对可以加载的 TLS 部分的数量也有下限。超过 TLS 部分限制可能会导致崩溃。如果这是您代码中的问题,尤其是 必须在旧操作系统上运行的代码,请使用 /Zc:threadSafeInit- 禁用线程安全初始化代码。
【讨论】:
以上是关于thread_local unordered_map 加上 AccessibleObjectFromWindow 不在 WinXP 中运行的主要内容,如果未能解决你的问题,请参考以下文章
C++:如何使用thread_local来声明一个指针变量?
跨内核线程迁移后是不是可以强制重新加载 thread_local 变量?