当前位置: 首页 > news >正文

使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题

目录

1、问题说明

2、问题分析思路

3、问题分析过程

3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,查看出问题的库

3.2、使用PE工具查看dll库的时间戳

3.3、解决办法

4、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       安装了新版本的安装包之后,启动程序时会报错,导致程序启动失败。这是日常工作中比较常见的一类问题,本文详细讲述如何使用PE信息查看工具和Dependency Walker工具去分析这类问题的完整过程,给大家提供一个借鉴或参考。

1、问题说明

       测试同事安装新版本的安装包之后,一启动程序就会报错,弹出如下的报错提示框:

导致程序启动失败。提示无法在xxsysctrldll.dll库中找不到InitMtDsc接口,这是一类比较常见的问题,一般都是因为主程序中有dll库的版本不一致引起的。比如A.dll依赖了B.dll库,出现接口找不到的问题,可能的原因有:

1)B.dll中的function接口不存在或者已经被删除了。比如老版本的A.dll和新版本的B.dll混在一起使用,老版本A.dll调用了function接口,但该接口在新版本的B.dll中已经删除或者已经更改名称了,所以会出现找不到接口的问题。比如新版本的A.dll和老版本的B.dll混在一起使用,新版本的A.dll调用了新版本的B.dll中新增的接口,但当前软件打包的还是老版本的B.dll,所以程序运行时在老版本B.dll中找不到接口。
2)B.dll中的function接口参数修改了。C++中支持函数重载(函数名称一样,但参数不一样),在编译时默认情况下会对函数名称进行改编,在生成的函数符号中融入了参数信息,比如上面截图中的 ?lnitMtDsc@@YAXGH@Z。

在B.dll中的function接口还在,但是参数修改了,函数符号发生了变化,所以找不到了。 


       在这里,给大家重点推荐一下我的几个热门畅销专栏:

专栏1:(该专栏订阅量接近350个,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据近几年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的实战问题分析实例,带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

专栏中的文章均是通过项目实战总结出来的(通过项目实战积累了大量的异常排查素材和案例),有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域的多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3: 

开源组件及数据库技术icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html

以多年的开发实战为基础,分享一些开源组件及数据库技术! 


2、问题分析思路

       对于上述这类问题,基本就是库的版本不一致导致的,具体是哪个库的版本有问题,我们使用PE信息查看工具和Dependency Walker工具就能快速排查出来。

       先使用Dependency Walker打开exe主程序,查看库与库的依赖关系,比如:

确定问题出在哪些个库中,同时可以进一步的确定是找不到库,还是调用的接口在目标dll库中找不到,亦或是要调用的接口在目标dll库中修改了参数。

       然后使用PE信息查看工具打开出问题的dll库文件,查看库文件的时间戳,比如:

即库文件(二进制文件)的编译生成时间,这样我们就能确定到底是哪个库的版本不对了。

       另外,在这个分析过程中,我们可能需要在svn或git上查看库文件的发布记录,和相关模块开发维护团队确认库与库之间的版本对应关系。

3、问题分析过程

3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,查看出问题的库

       首先我们使用Dependency Walker打开软件的exe主程序,查看库与库之间的依赖关系,看看问题具体出在哪些库中。

       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错误icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131505299此外,很多系统库节点前面也会显示一个黄色的问号图标,这些系统库一般可以忽略掉,不用管。
2)在某个库中找不到调用的接口,会在对应的接口行前面显示一个红色的图标如下所示:

可能这个接口在库中已经不存在了(被删除了),也可能是接口的参数修改了,生成的函数符号变了。

        在本案例中,最开始启动程序报错的截图如下:

从这个截图可以看出,问题与xxsysctrldll.dll库有关。用Dependency Walker打开exe主程序后,显示出问题的两个库的截图如下所示:

首先看到xxsysctrldll.dll依赖了xxdscdll.dll,之所以依赖,肯定是xxsysctrldll.dll库中调用了xxdscdll.dll库中的接口。然后我们看到xxdscdll.dll节点前面有淡红色的异常图标,所以我们点击xxdscdll.dll节点,此时右边实现两块信息,上面PI部分是依赖该库的xxsysctrldll.dll从该库中引入了哪些接口,即xxsysctrldll.dll库中调用了xxdscdll.dll库中的那些接口;下面的E部分,是当前xxdscdll.dll库有哪些导出接口。

关于导出导入,对于dll动态库本身,接口是导出的,是要提供给其他库调用的;对于使用到该库的其他库,需要引入当前库的接口,然后调用这些接口的。一般可以使用#import导入dll库对应的.lib库,比如#pragma comment( lib, "winmm.lib" ) ,这个是在编译链接时会用到,如果找不到调用的接口符号,则会编译报错。接口的运行调用则时发生在程序运行阶段的。

       看到导入列表中的接口?InitMtDsc@@YAXGH@Z(这是经过编译器名称改编后的函数名称,带了参数信息)所在行前面显示了红色的图标,应该是该接口符号,在当前的xxdscdll.dll中没有。可以翻看下方的xxdscdll.dll的导出函数列表,看看xxdscdll.dll有没有导出InitMtDsc接口。在xxdscdll.dll导出接口的列表中确实找到了InitMtDsc接口,但包含了参数信息的改编后的名称是不一样的,即?InitMtDsc@@YAXG@Z,所以应该是该接口的参数修改了。

       目前可以确定是xxdscdll.dll与xxsysctrldll.dll两个库不匹配,但具体是哪个库有问题,还是看这两个库的时间戳(库的编译生成时间)

3.2、使用PE工具查看dll库的时间戳

       此时我还要使用到PeViewer PE信息查看工具。打开PeViewer工具,点击打开按钮,找到xxdscdll.dll与xxsysctrldll.dll文件的路径,打开文件查看到文件的时间戳:(点击左侧列表中的头部 -> NT头 -> 文件头右侧就会显示文件的时间戳)

从上图中可以看到,xxdscdll.dll库的时间戳为2023/12/07[04:29:53],xxsysctrldll.dll库的时间戳为2023/12/15[15:29:37]。 

我这边经常使用的PE信息查看工具叫PeViewer,以前排查问题时,用该工具打开64位二进制文件发生了闪退。后来在网上搜到了MiTeC EXE Explorer工具,这个工具兼容性比较好,打开64位二进制文件没有问题。大家后面遇到问题时,可以使用更强大的MiTeC EXE Explorer。

       最近底层的组件有多个模块有改动,12月15日有发布新库过来,查看了svn上的发布记录:

发布说明中提及到的发布模块中有提到xxdscdll模块和xxsysctrldll模块,但实际上并没有发布库文件xxdscdll.dll,xxsysctrldll.dll库文件发布过来了。所以结合上面的PE工具查看的时间戳,xxsysctrldll.dll是最新版本,但xxdscdll.dll是老版本

       那明明发布说明中指出要发布xxdscdll模块过来,为啥没发布成功呢?先到文件服务器上查看编译日志,看看是不是xxdscdll模块代码编译失败了。经查看,xxdscdll模块编译没有错误的,文件有生成的。于是找了一下配置管理员,他查看了一下发布模块配置,发现了问题:

在配置发布模块xxdsc的名称时,错误地将xxdscdll.dll写成了xxdssdll.dll(将dsc写成dss),导致了自动执行发布脚本时没有拷贝xxdscdll.dll到指定产品的代码流上。

3.3、解决办法

       所以在该问题场景中,新版本的xxsysctrldll.dll使用了老版本的xxdscdll.dll,新版本的xxsysctrldll.dll调用了新版本的xxdscdll.dll中的InitMtDsc接口,在新版本的xxdscdll.dll中修改了InitMtDsc接口的参数,即新版本的xxdscdll.dll调用了修改参数后的InitMtDsc接口,所以在老版本的xxdscdll.dll中找不到修改参数后的InitMtDsc接口,所以程序启动时弹出了文章最开始说到的错误提示框:

解决办法很简单,只需要将漏发的xxdscdll.dll文件发布过来就好了。

4、最后

       本案例中详细介绍了如何使用PE信息查看工具与Dependency Walker去排查程序启动报错的问题,希望能给大家提供一定的借鉴或参考。

相关文章:

使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题

目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序,查看库与库的依赖关系,查看出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总(专栏文章列表&…...

Python编程题目答疑「Python一对一辅导考试真题解析」

你好,我是悦创。 待会更新~ 更新计划 答案 题目 记得点赞收藏! 题目 之后更新 Solution Question 1 # 读取输入 a float(input("请输入实数 a: ")) b float(input("请输入实数 b: ")) c float(input("请输…...

Python---搭建Python自带静态Web服务器

1. 静态Web服务器是什么? 可以为发出请求的浏览器提供静态文档的程序。 平时我们浏览百度新闻数据的时候,每天的新闻数据都会发生变化,那访问的这个页面就是动态的,而我们开发的是静态的,页面的数据不会发生变化。 …...

在服务器上部署SpringBoot项目jar包

以下是在服务器上部署Spring Boot项目jar包的步骤: 打包项目: 使用IDEA或者命令行工具(如Maven或Gradle)将Spring Boot项目打包为一个可执行的jar文件。如果使用Maven,可以在项目的根目录下运行以下命令来打包项目&…...

[python]python实现对jenkins 的任务触发

目录 关键词平台说明背景一、安装 python-jenkins 库二、code三、运行 Python 脚本四、注意事项 关键词 python、excel、DBC、jenkins 平台说明 项目Valuepython版本3.6 背景 用python实现对jenkins 的任务触发。 一、安装 python-jenkins 库 pip install python-jenkin…...

Python生成圣诞节贺卡-代码案例剖析【第18篇—python圣诞节系列】

文章目录 ❄️Python制作圣诞节贺卡🐬展示效果🌸代码🌴代码剖析 ❄️Python制作圣诞树贺卡🐬展示效果🌸代码🌴代码剖析🌸总结 🎅圣诞节快乐! ❄️Python制作圣诞节贺卡 …...

深度剖析Ajax实现方式(原生框架、JQuery、Axios,Fetch)

Ajax学习 简介: ​ Ajax 代表异步 JavaScript 和 XML(Asynchronous JavaScript and XML)的缩写。它指的是一种在网页开发中使用的技术,通过在后台与服务器进行数据交换,实现页面内容的更新,而无需刷新整个…...

任天堂,steam游戏机通过type-c给VR投屏与PD快速充电的方案 三type-c口投屏转接器

游戏手柄这个概念,最早要追溯到二十年前玩FC游戏的时候,那时候超级玛丽成为了许多人童年里难忘的回忆,虽然长大了才知道超级玛丽是翻译错误,应该是任天堂的超级马里奥,不过这并不影响大家对他的喜爱。 当时FC家用机手柄…...

Flink系列之:Checkpoints 与 Savepoints

Flink系列之:Checkpoints 与 Savepoints 一、概述二、功能和限制 一、概述 从概念上讲,Flink 的 savepoints 与 checkpoints 的不同之处类似于传统数据库系统中的备份与恢复日志之间的差异。 Checkpoints 的主要目的是为意外失败的作业提供恢复机制。 …...

【优质书籍推荐】LoRA微调的技巧和方法

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…...

Linux一行命令配置jdk环境

使用方法: 压缩包上传 到/opt, 更换命令中对应的jdk包名即可。 注意点:jdk-8u151-linux-x64.tar.gz 解压后名字是jdk1.8.0_151 sudo tar -zxvf jdk-8u151-linux-x64.tar.gz -C /opt && echo export JAVA_HOME/opt/jdk1.8.0_151 | sudo tee -a …...

从0开始刷剑指Offer

剑指Offer题解 剑指 Offer 11. 旋转数组的最小数字 思路: 二分O(logn) class Solution {public int stockManagement(int[] stock) {int l 0;int r stock.length - 1;while(l < r && stock[0] stock[r]) r --;if(stock[r] > stock[l]) return stock[0];whi…...

使用Java语言中的算法输出杨辉三角形

一、算法思想 创建一个名为YanghuiTest的类,然后创建二维数组&#xff0c;然后遍历二维数组的第一层&#xff0c;然后初始化第二层数组的大小&#xff0c;然后遍历第二层数组&#xff0c;然后将两侧的数组元素赋为1&#xff0c;然后其它数值通过公式计算&#xff0c;最后可以输…...

人工智能_机器学习071_SVM支持向量机_人脸识别算法_LFW人脸数据加载_与理解---人工智能工作笔记0111

然后我们继续来看 这里有个lfw_home可以看到这个数据是,包含了人脸数据 然后我们继续看,在我们的顶你用户目录下,如果安装了,sklearn就会有这样一个目录, scikit_learn_data目录,这个里面可以看到 可以看到这个文件夹中有个 lfw_home文件夹是对.zip文件夹的解压,这个下载以后…...

Java 8中流Stream API详解

先给个示例&#xff0c;展示Java 8流API的优势 假设我们有以下任务&#xff1a; 给定一个字符串列表&#xff0c;我们需要执行以下操作&#xff1a; 筛选出所有以"A"开头的字符串。 将这些字符串转换为大写。 对这些字符串按照长度进行排序。 最后&#xff0c;将…...

通过 xlsx 解析上传excel的数据

一、前言 在前端开发中&#xff0c;特别是在后台管理系统中&#xff0c;导入数据&#xff08;上传excel&#xff09;到后端是是否常见的功能&#xff1b;而一般的实现方式都是通过接口将excel上传到后端&#xff0c;再有后端进行数据解析并做后续操作。 今天&#xff0c;来记录…...

Flink系列之:JDBC SQL 连接器

Flink系列之&#xff1a;JDBC SQL 连接器 一、JDBC SQL 连接器二、依赖三、创建 JDBC 表四、连接器参数五、键处理六、分区扫描七、Lookup Cache八、幂等写入九、JDBC Catalog十、JDBC Catalog 的使用十一、JDBC Catalog for PostgreSQL十二、JDBC Catalog for MySQL十三、数据…...

OpenCV与YOLO学习与研究指南

引言 OpenCV是一个开源的计算机视觉和机器学习软件库&#xff0c;而YOLO&#xff08;You Only Look Once&#xff09;是一个流行的实时对象检测系统。对于大学生和初学者而言&#xff0c;掌握这两项技术将大大提升他们在图像处理和机器视觉领域的能力。 基础知识储备 在深入…...

hive中map相关函数总结

目录 hive官方函数解释示例实战 hive官方函数解释 hive官网函数大全地址&#xff1a; hive官网函数大全地址 Return TypeNameDescriptionmapmap(key1, value1, key2, value2, …)Creates a map with the given key/value pairs.arraymap_values(Map<K.V>)Returns an un…...

HttpServletRequestWrapper、HttpServletResponseWrapper结合 过滤器 实现接口的加解密、国际化

目录 一、HttpServletRequestWrapper代码 二、HttpServletRequestWrapper代码 三、加解密过滤器代码 四、国际化过滤器代码 一、HttpServletRequestWrapper代码 package com.vteam.uap.security.httpWrapper;import jakarta.servlet.ReadListener; import jakarta.servlet.…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...