C/C++教程

使用Visual C++高版本的XP支持生成带boost执行文件在XP上报kernel32缺函数

本文主要是介绍使用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”,典型的找不到的有InitializeSRWLockInitializeCriticalSectionExGetLogicalProcessorInformation等。
dumpbin /imports能看到对上述函数的引用,但根据MSDN说法,这些函数只在Vista及之后的版本才提供,与编译器的XP支持的设定不符。

病因分析

显然出现这些问题是因为代码里指示了要用这些函数。但到底是哪里用到了呢?参考文献3描述了一次分析过程。
这里直接给结论。主要问题在于

  1. <mutex><thread>等的引用链条当中有地方使用了这些函数,根据参考文献4的分析,可能是只做了64位XP的适配,毕竟这个年代没什么商业软件用XP的需求了,而工业软件很多懒得换工具链;
  2. 生成和使用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上运行成功了。

参考资料

  1. 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 .
  2. 码农老宋. boost::thread支持XP SP2 [EB/OL]. https://blog.csdn.net/qq_30773619/article/details/102708604 .
  3. 文大侠. C++ 11 thread静态链接getlogicalprocessorinformation导致错误 [EB/OL]. https://blog.csdn.net/wenzhou1219/article/details/78242321 .
  4. nature19862001. 关于Windows XP SP2 x86上不支持的两个C++11 [EB/OL]. https://blog.csdn.net/nature19862001/article/details/69952434 .
这篇关于使用Visual C++高版本的XP支持生成带boost执行文件在XP上报kernel32缺函数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!