目录
1、问题说明
2、使用Dependency Walker工具查看exe主程序的库依赖关系,但找到mtsysctrldll.dll库
3、使用dumpbin工具查看mtsysctrldll.dll库是被哪个dll库依赖的
3.1、 dumpbin工具介绍
3.2、 使用dumpbin工具查看依赖mtsysctrldll.dll的库
C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...) https://blog.csdn.net/chenlycly/article/details/125529931 我们在开发C++软件的过程中,因为软件模块比较繁多,经常会出现底层库版本不一致的问题。其中有一种是dll库中缺少接口,会导致软件启动报错问题,今天我们就来详细讲述一下如何使用dumpbin.exe和Dependency Walker工具来定位这类问题。
某天安装早上编译的安装包后启动主程序失败,弹出如下的报错提示框:
即无法定位程序输入点SrvSetAutoByteTimeout于动态库mtsysctrldll.dll上。这句话并不是mtsysctrldll.dll库中缺少这个接口,这个接口是mtsysctrldll.dll从其依赖的dll库中导入的,但实际运行时mtsysctrldll.dll无法从其依赖的dll库中找到该接口。
本文讲述的是静态链接进来的库加载失败的情况,会弹出上面的报错提示框。如果是通过LoadLibrary等接口去动态加载的库加载失败了,则不会弹出报错提示框,会有较强的隐蔽性,可以参见我之前写的一篇文章:
使用Process Explorer和Dependency Walker定位dll库动态启动失败的问题https://blog.csdn.net/chenlycly/article/details/125216591
对于找不到接口的问题,一般使用Dependency Walker看一下目标库的依赖情况,看看到底是依赖的哪个库中找不到对应的接口。
启动exe程序时,系统会先把exe文件依赖的所有的dll库文件加载到进程空间中,然后才会进入到exe程序的main函数,程序才能运行起来。
exe程序会直接依赖一些dll库,这些dll库可能还会依赖其他的dll库,启动exe程序时会把所有有依赖关系的库都加载到进程空间中。
Dependency Walker工具主要有三个用处:
1)查看目标库到底依赖了哪些库;
2)查看依赖的库是否存在,如果不存在会显示黄色的问号;
3)调用依赖的库中的接口是否存在,如果不存在,则会显示红色标记。
于是使用Dependency Walker打开exe主程序,然后将依赖列表中的节点都展开,然后找到mtsysctrldll.dll库节点,然后就能确定是哪个库中找不到SrvSetAutoByteTimeout接口。
如果你机器用的是Win10系统,Dependency Walker工具对win10的兼容性不太好,打开exe程序时非常慢,有时会卡好几分钟甚至需要更长的时间,需要耐心等一下。
Dependency Walker成功打开exe主程序后的效果如下:
因为我们软件底层有上百个模块,这些模块是多个组维护的,出问题的mtsysctrldll.dll库也是底层的,所以我们搞不清楚底层库的依赖关系,结果在exe主程序的依赖列表中并没有找到mtsysctrldll.dll。由于主程序依赖的库达到上百个,我们不知道mtsysctrldll.dll到底位于哪个库下面。所以我们还需要借助其他工具来辅助看一下。
我们不知道mtsysctrldll.dll库被哪个库依赖了,即在依赖列表中mtsysctrldll.dll库的父节点是谁,可以使用dumpbin工具找到其父节点,如果在Dependency Walker中还看不到,可能还要向上找父节点,直到我们能在Dependency Walker中很容易找到为止。
我们可以使用微软的dumpbin工具将软件安装目录中的所有二进制文件的依赖关系都打印到文件,然后在文件中搜索mtsysctrldll.dll,就能找到是哪个库依赖了mtsysctrldll.dll了。
只要是安装Visual Studio的,在Visual Studio的安装路径下的VC\bin目录中就能找到dumpbin.exe程序,比如我机器上对应的路径为:
D:\Program Files(x86)\Microsoft Visual Studio10.0\VC\bin
dumpbin.exe是微软提供的二进制文件信息查看工具,安装Visual Studio(IDE开发环境)时会自动安装该工具,该工具位于安装路径的VC目录中。使用该工具可以查看.exe、.dll等二进制文件的库依赖关系、导出接口等信息。
我们也可以在Visual Studio开始菜单中找到直接切入到命令行环境的命令行快捷方式,如下所示:
点击后就会弹出cmd命令行窗口,如下所示:
在该命令行窗口中设置了相关路径的环境变量,其中就包含dumpbin.exe所在的路径,所以在该命令行中就可以直接输入dumpbin.exe,直接运行该程序。
我们可以输入“dumpbin.exe /?”,查看dumpbin.exe支持哪些命令行参数,如下所示:
其中常用的参数有:
1)/Dependents:查看二进制文件都依赖了哪些库。
2)/EXports:查看dll库的导出接口信息。
本例中我们使用/Dependents参数,然后再使用">"重定向操作符(cmd命令行中支持),将输出信息输出到文件中,方便查看搜索。具体的命令如下:
dumpbin /dependents "D:\Program Files(x86)\WYLink\*.dll" > d:\0710-dlldepemdents.txt
上述命令是将D:\Program Files(x86)\WYLink目录下的所有dll的依赖库信息打印出来,输出到d:\0710-dlldepemdents.txt文件中。
执行上述命令后,我们打开d:\0710-dlldepemdents.txt文件,然后在文件中搜索mtsysctrldll.dll字符换,找到了对应的条目,如下所示:
从上图可以看出,是mtkernelapidll.dll库依赖了mtsysctrldll.dll,所以我们到Dependency Walker中的依赖关系列表中去找mtkernelapidll.dll库,找到了,如下所示:
于是查看mtkernelapidll.dll的子节点,找到mtsysctrldll.dll节点,然后再查看mtsysctrldll.dll的子节点,发现其下的一个节点图标显示红色,就是这个库的问题。点击该问题节点,右边显示的PI导入函数列表中SrvSetAutoByteTimeout函数前面的图标显示红色,说明这个函数是找不到的。该PI列表是左边选中的模块被其父节点库引入的导入函数列表。
所以肯定是这个库版本不对了,经过和维护该库的开发人员确认,出问题的SrvSetAutoByteTimeout接口是最近新增的接口,应该是软件安装包中使用的库是老版本,重新将最新的库发布过来就好了。