使用Visual C++高版本的XP支持生成带boost执行文件在XP上报kernel32缺函数
作者:互联网
典型症状
使用Visual Studio 2019,安装“对VS 2017 (v141)工具的C++ Windows XP支持”后,用该v141_xp
平台工具集生成的执行文件在Windows XP SP3下仍无法运行,Release版本报错,Debug版本提示“在KERNEL32.DLL中找不到xxxxxx”,典型的找不到的有InitializeSRWLock
或InitializeCriticalSectionEx
或GetLogicalProcessorInformation
等。
用dumpbin /imports
能看到对上述函数的引用,但根据MSDN说法,这些函数只在Vista及之后的版本才提供,与编译器的XP支持的设定不符。
病因分析
显然出现这些问题是因为代码里指示了要用这些函数。但到底是哪里用到了呢?参考文献3描述了一次分析过程。
这里直接给结论。主要问题在于
<mutex>
和<thread>
等的引用链条当中有地方使用了这些函数,根据参考文献4的分析,可能是只做了64位XP的适配,毕竟这个年代没什么商业软件用XP的需求了,而工业软件很多懒得换工具链;- 生成和使用boost时需要指明对XP的兼容。
解决方法
一方面,要用兼容XP的方式生成boost的thread等库。根据参考文献1,以及对涉及到的库的代码研究,在用b2生成库时,需要加如下参数(但这么写的结果不对,见下文说明):
define=BOOST_USE_WINAPI_VERSION=0x0501 define=_WIN32_WINNT=0x0501 define_BOOST_USE_WINDOWS_H
同时,考虑到v141_xp
平台工具集会修改引用目录等,需要在编译boost之前先调整环境变量。环境变量可以从使用v141_xp
平台工具集的项目的属性里复制。
另一方面,如果代码中使用了 <mutex>
和<thread>
等,需要把它们换成boost的对应物。同时也需要给项目的编译条件添加上面的宏定义。
理论上似乎这样就好了,但实际上使用了上述手段之后,仍然会莫名其妙地存在对高版本API的引用。参考文件2里描述了这个奇怪的现象,并提供了解决方法:BOOST_USE_WINAPI_VERSION
的值,设定时候不能写字面值,要写成常量宏BOOST_WINAPI_VERSION_WINXP
。奇怪的是这样的确就好了。
define=BOOST_USE_WINAPI_VERSION=BOOST_WINAPI_VERSION_WINXP define=_WIN32_WINNT=0x0501 define_BOOST_USE_WINDOWS_H
这样生成出来的执行文件在XP上运行成功了。
参考资料
- Morell, René Ferdinand Rivera; Prus, Vladimir; Watanabe, Steven. B2 User Manual [EB/OL]. https://www.boost.org/doc/libs/1_77_0/tools/build/doc/html/index.html .
- 码农老宋. boost::thread支持XP SP2 [EB/OL]. https://blog.csdn.net/qq_30773619/article/details/102708604 .
- 文大侠. C++ 11 thread静态链接getlogicalprocessorinformation导致错误 [EB/OL]. https://blog.csdn.net/wenzhou1219/article/details/78242321 .
- nature19862001. 关于Windows XP SP2 x86上不支持的两个C++11 [EB/OL]. https://blog.csdn.net/nature19862001/article/details/69952434 .
标签:USE,kernel32,BOOST,WINAPI,Visual,XP,boost,define 来源: https://www.cnblogs.com/logischerweise/p/15187710.html