目录
1、问题说明
2、使用Dependency Walker查看工具程序的库依赖关系
3、在可以运行的电脑上使用Process Explorer查看依赖的msvcr120.dll和msvcp120.dll库的路径
4、C/C++运行时库介绍
5、可以下载安装VC_redist.x86.exe或VC_redist.x64.exe解决系统库缺失问题
C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++基础与进阶(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_11931267.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_2276111.html 安卓开发组的同事在调试使用瑞芯微主控CPU芯片的嵌入式设备(嵌入式设备使用的是Android系统)时,需要在PC上使用瑞芯微提供的一个工具软件去配置图像质量参数,但这个工具启动时会报错,无法运行。同事找到我,让我帮他们看看是怎么回事,看能否让这个工具正常跑起来。
1、问题说明
部分嵌入式设备使用的是安卓系统,两年前使用的CPU主控芯片是华为海思的,因为华为被制裁,海思芯片无法供货,所以转而使用国内二线芯片厂商的CPU芯片,最终选择的是瑞芯微。
使用了一段时间的瑞芯微CPU芯片,这些二线厂商的芯片实在是一言难尽,无论是性能,还是稳定性,亦或是功能的完备性,都和海思有较大的差距。以前能正常使用海思芯片的时候,不觉得,断供后才知道海思的芯片是真的好用!没有对比就没有伤害!
在设备调试的过程中遇到了一些问题,需要使用瑞芯微提供的软件工具去远程配置图像质量参数,但拿到工具后却运行不起来。在一台笔记本上双击该软件程序,就会弹出如下的错误:
安卓开发组的同事是专职做安卓app开发的,对Windows程序开发不太了解,于是找到我,希望我帮他们看一下,看看怎么回事,看看能否把软件运行起来。
在这里,给大家重点推荐一下我的几个热门畅销专栏:
专栏1:(该专栏订阅量接近350个,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!)
C++软件调试与异常排查从入门到精通系列文章汇总https://blog.csdn.net/chenlycly/article/details/125529931
本专栏根据近几年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的实战问题分析实例,带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!
专栏中的文章均是通过项目实战总结出来的(通过项目实战积累了大量的异常排查素材和案例),有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!
专栏2:
C/C++基础与进阶(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_11931267.html
以多年的开发实战为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域的多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!
专栏3:
开源组件及数据库技术https://blog.csdn.net/chenlycly/category_12458859.html
以多年的开发实战为基础,分享一些开源组件及数据库技术!
2、使用Dependency Walker查看工具程序的库依赖关系
我们做Windows开发的,对这个报错提示框比较熟悉,这个是因为这个软件工具依赖了msvcr120.dll,但在出问题的笔记本上找不到这个库。程序启动时,会先将依赖的dll库加载到进程空间中,等所有依赖的库加载到进程空间中后,就会将主程序运行起来。如果在加载依赖的库在系统找不到时,就会报类似下面的错误:
除了这个库,可能还缺少其他库,可以直接将查看库依赖关系的Dependency Walker拷贝到这台无法运行的电脑上,直接用该工具查看exe主程序依赖的哪些库在该机器上找不到。
在本例中,我们将Dependency Walker拷贝到笔记本上,并将之双击运行起来,然后将软件工具的exe主程序文件RKPQTool.exe拖到Dependency Walker中,等待Dependency Walker打开完成。
Dependency Walker打开exe主程序后,会以树状结构将exe主程序依赖的库以及这些库依赖的其他库展示出来。默认情况下,会自动将树中的节点全部展开。
注意一下,当前最新的Dependency Walker还是2016年的,当运行在Win10等新的系统中时,打开文件可能会比较慢,甚至要等好几分钟才能打开完成,要稍微耐心等待一下。
在展开的树中,节点太多,除了软件的业务库,还包含大量的Windows系统库,为了方便查看,我们可以将系统库的节点给折叠起来。这就要求我们要识别出来哪些库是系统库,比如常见的user32.dll、ntdll.dll、kernel32.dll,还有以API-MS-WIN开头的系统库:
这对于经常搞Windows软件开发的人很简单,但对于新手或者不熟悉Windows软件开发的人来说,可能很难分辨。
在Dependency Walker中,如果库找不到或者库中的接口有问题,问题节点前面会显示特别的异常图标:
1)在运行的机器中找不到某个库,会在该库的节点前显示一个黄色的问号图标,如下所示:
这可能是打包软件时,没有将程序依赖的库打包进安装包中。比如忘记将一个新增的dll库打包到安装包中、没有将运行时库打包到安装包中。注意,不同版本的Visual Studio使用的运行时库名称是不一样的,比如Visual Studio 2010的运行时库是msvcr100.dll和msvcp100.dll,Visual Studio 2017的运行时库是msvcp140.dll、vcruntime140.dll和ucrtbase.dll(不再有msvcr140.dll、新增了vcruntime140.dll和ucrtbase.dll)。
使用Visual Studio编译出来的程序,在打安装包时都需要把对应版本的运行时库打包进去。关于不同Visual Studio版本对应的运行时库的详细说明,可以参见我的文章:使用Dependency Walker和Process Explorer排查程序启动时缺少ucrtbase.dll等运行时库以及报0xC000007B错误https://blog.csdn.net/chenlycly/article/details/131505299此外,很多系统库节点前面也会显示一个黄色的问号图标,这些系统库一般可以忽略掉,不用管。
2)在某个库中找不到调用的接口,会在对应的接口行前面显示一个红色的图标,如下所示:可能这个接口在库中已经不存在了(被删除了),也可能是接口的参数修改了,生成的函数符号变了。
在本案例中,我们将系统库折叠起来之后,看到了如下的结果:
我们从上图中可以看出,依赖的两个库msvcr120.dll和msvcp120.dll在这台笔记本上找不到。
3、在可以运行的电脑上使用Process Explorer查看依赖的msvcr120.dll和msvcp120.dll库的路径
上述工具软件缺少msvcr120.dll和msvcp120.dll两个库,这两个是微软IDE开发工具Visual Studio 2013自带的运行时库,使用Visual Studio 2013开发的程序会依赖这两个库,在程序发布时需要将这两个运行时库带上的(放置在exe主程序的同级目录中)。当前RKPQTool工具是瑞芯微开发并提供的,应该是瑞芯微在打包程序时把这两个库带上的,结果没带上,这点确实不太专业。可能他们是做硬件的公司,软件这块做的比较少。
将RKPQTool工具拷贝到我们的开发机器上,是可以正常运行的。
我们开发的机器上安装了多个版本的Visual Studio,安装Visual Studio时会将对应版本的运行时库拷贝到Windows系统目录中。
可以使用Process Explorer查看已经运行起来的程序加载的msvcr120.dll和msvcp120.dll库是哪个路径下的。在进程列表中找到RKPQTool.exe进程,左键点击进程,则下方就会显示该进程加载的动态库列表,在加载的动态库列表中找到msvcr120.dll和msvcp120.dll两个文件:
根据文件显示的路径将文件拷贝出来,然后拷贝到RKPQTool.exe所在的目录中即可,双击RKPQTool.exe就能运行起来了。
4、C/C++运行时库介绍
这个案例中涉及到的msvcp120.dll和msvcr120.dll,他们是C/C++运行时库,所以此处我们正好给大家讲讲C/C++运行时库相关的内容。
我们代码中调用的很多C/C++基本库函数都位于C/C++运行时库中,比如abort、system、strlen、strcpy等运行时库函数。一般运行时库是以msvcr(C运行时库)或msvcp(C++运行时库)开头的。不同版本的Visual Studio携带的C/C++运行时dll库的版本可能也不一样,这些运行时库一般要打包到安装程序中,安装时要拷贝到exe主程序的安装目录中。
关于不同版本的Visual Studio对应的运行时库版本,很多人可能分不清楚,会有疑惑,这里详细给大家介绍一下:(以d结尾的是Debug版本的运行时库)
1)VS2010对应的运行时库文件(对应100版本):msvcp100.dll(msvcp100d.dll)、msvcr100.dll(msvcr100d.dll);
2)VS2012对应的运行时库文件(对应110版本):msvcp110.dll(msvcp110d.dll)、msvcr110.dll(msvcr110d.dll);
3)VS2013对应的运行时库文件(对应120版本):msvcp120.dll(msvcp120d.dll)、msvcr120.dll(msvcr120d.dll);
4)VS2017对应的运行时库文件(对应140版本):msvcp140.dll(msvcp120d.dll)、ucrtbase.dll(ucrtbased.dll)、vcruntime140.dll(vcruntime140d.dll); (VS2017引入了两个新库ucrtbase.dll、vcruntime140.dll,不再有msvcr140.dll库,只保留了msvcp140.dll库)
以msvcp110.dll文件,在文件属性中可以看到其对应的版本为VS2012,如下所示:
关于运行时库更详细的说明,可以参见我之前写的文章:
使用Dependency Walker和Process Explorer排查程序启动时缺少ucrtbase.dll等运行时库以及报0xC000007B错误https://blog.csdn.net/chenlycly/article/details/131505299
5、可以下载安装VC_redist.x86.exe或VC_redist.x64.exe解决系统库缺失问题
上述通过Dependency Walker和Process Explorer工具去排查定位问题,略显麻烦,对于这类缺少运行时库的问题,可以直接到微软官方网站下载VC_redist.x86.exe或VC_redist.x64.exe,然后执行安装,会将指定版本的运行时库安装到系统目录中。
关于VC_redist.x86.exe和VC_redist.x64.exe的详细介绍,可以参看我之前写的文章:
下载最新版 VC_redist.x86.exe / VC_redist.x64.exe for Visual Studio 2015, 2017, 2019, and 2022https://blog.csdn.net/chenlycly/article/details/131451865