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_localunordered_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 中运行的主要内容,如果未能解决你的问题,请参考以下文章

线程本地存储,thread_local关键字是必须的吗?

非静态数据成员的 thread_local 数据,再次

C++:如何使用thread_local来声明一个指针变量?

跨内核线程迁移后是不是可以强制重新加载 thread_local 变量?

具有与 std::thread 不同的线程库的 C++ thread_local

C++ 程序结束时的 thread_local 向量分段错误