C++程序在Windows系统上启动失败与运行卡死问题排查实战

news2024/12/23 22:17:47

目录

1、VS2017默认编译出来的程序,不支持XP系统

1.1、新版本软件为什么要选择VS2017?

1.2、VS2017如何配置才能编出支持XP系统的程序?

1.3、最终选择使用VS2010编出的版本

2、程序在XP系统中启动报错,无法启动

2.1、提示在系统库MFPlat.dll中找不到MFGetStrideForBitmapInfoHeader接口

2.2、Microsoft Media Foundation多媒体库不支持XP系统

2.3、为啥会报找不到MFGetStrideForBitmapInfoHeader接口

2.4、在两个XP系统中表现现象不太一样

2.5、此问题的解决办法

3、程序执行某一操作时发生了线程卡死问题

3.1、将Windbg附加到目标进程上初步分析卡死的原因

3.2、从动态调试的Windbg中导出dump文件,事后进行进一步分析

3.3、加载系统pdb文件后可能会看到更详细的函数调用堆栈

3.4、本问题的解决办法    

4、总结


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具案例集锦(正在更新中...)https://blog.csdn.net/chenlycly/category_12279968.html       在最近某个项目中,客户环境中还有安装很老的XP系统的机器,要求我们的软件支持XP系统。在XP系统中进行测试验证时遇到程序启动失败和线程卡死两个典型的异常问题,今天在这里分享一下这两个问题的排查过程。

1、VS2017默认编译出来的程序,不支持XP系统

       最近因项目需要,引导客户对系统升级扩容,将服务器系统升级到一个比较新的版本,但客户用的客户端软件是几年前发布的老版本,为了能很好的兼容新平台,需要将客户用的客户端软件升级到最新版本。在客户环境中还有部分电脑使用的Windows XP系统,所以客户端软件需要支持XP系统。

现在使用XP系统的应该非常少了,可能有小部分老电脑还在使用。使用Win7的应该也不多了,大部分人都在使用Win10或者最新的Win11系统,特别是新买的电脑上默认安装的都是最新的Win11系统。

但最新版本的客户端的IDE开发环境已经升级到VS2017,默认情况下VS2017编译出来的程序是不支持XP系统的,但客户的环境中还有部分机器在用XP系统,所以不能使用最新的客户端软件。

1.1、新版本软件为什么要选择VS2017?

       为啥我们的客户端的开发工具要升级到VS2017呢?因为我们项目中使用到了开源的WebRTC库,开源的WebRTC库需要使用VS2017或以上版本编译。因为不同VS版本的库混用可能会出现不匹配的问题,所以需要将产品从上到下的模块都升级到VS2017版本。

       那开源WebRTC库能否使用低版本的Visual Studio去编译呢?我们软件以前是使用VS2010编译的,是支持XP系统的,能否使用VS2010编译开源的WebRTC库呢?我们使用的WebRTC库是比较新的开源版本,新版本的WebRTC代码中大规模地使用到了C++11及以上的新特性(很多开源代码都热衷于使用C++的新特性),而VS2010中只支持部分C++11的新特性(我们的项目中使用过auto关键字、匿名函数等C++11新特性,这些特性VS2010是支持的),所以将WebRTC代码拿到VS2010中编译肯定会有编译错误的。

C++11及以上的新特性,使得C++变得更加高效灵活,但也使得C++变得越来越臃肿,越来越难以驾驭!

其实直到VS2015才全面支持C++11,VS2015完对C++14的支持也基本完成,并支持部分C++17标准。

1.2、VS2017如何配置才能编出支持XP系统的程序?

       VS2017默认编译出来的程序只支持Vista及以上系统的。那能否修改配置,让VS2017编译出支持XP系统的程序呢?答案是可以的,这点我们之前有专门对demo程序测试过。在安装VS2017时,有个“对C++的WindowsXP的支持”组件选项:

勾选上该选项安装后,在工程属性的常规->平台工具集中切换平台工具集:

可以选择VisualStudio2017-WindowsXP(v141_xp)、VisualStudio2015-WindowsXP(v140_xp)或者VisualStudio2010(v100)工具集去编译出支持XP系统的版本。

如果大家在安装VS2017时,没有勾选“对C++的WindowsXP的支持”组件选项,可以直接在卸载程序中对其修改,勾选上该选项,在线安装即可。

但对于我们的产品,从上到下有上百个模块,都切换同样的平台工具集去编译,工作量会比较大,最终是否有问题还不得而知。如果是个简单的工具软件,模块很少,可以使用这个方法去解决。

1.3、最终选择使用VS2010编出的版本

       所以最终还是推荐使用VS2010编译的客户端版本,这个版本也是相对较新的,主要它是支持XP系统的。但这个版本没有引入WebRTC库,没法使用到WebRTC的特性。

2、程序在XP系统中启动报错,无法启动

       将VS2010编译出来的版本拿到XP系统上运行,启动会报错,程序启动失败。

2.1、提示在系统库MFPlat.dll中找不到MFGetStrideForBitmapInfoHeader接口

       将这个版本拿到客户的XP系统上安装后启动运行,结果刚启动就报错了,弹出如下的提示框:

在系统库MFPlat.dll中找不到MFGetStrideForBitmapInfoHeader接口,应该是我们的程序中调用到MFGetStrideForBitmapInfoHeader接口了,但在客户的系统中的MFPlat.dll库中找不到该接口。

在exe主程序启动时,系统需要先将exe主程序依赖的dll先加载到进程空间中(即先加载依赖的dll库),并且会校验各个模块中调用的接口在业务库或者系统库中能否找到接口,如果找不到接口,则会报错,就会终止程序的启动,程序启动失败。

2.2、Microsoft Media Foundation多媒体库不支持XP系统

        对于这个MF开头的接口和库名称,我是有点印象的,一两年前和音视频编解码组的同事一起排查某个客户遇到的USB摄像头采集出的图像会异常闪烁的问题,当时音视频编解码组的同事尝试将摄像头采集方案换成微软的Media Foundation多媒体解决方案,看看能不能解决问题,于是在代码中引入了Media Foundation库(几个MF开头的dll库)。

Media Foundation是微软在WindowsVista上推出的新一代多媒体应用库,目的是提供Windows平台一个统一的多媒体影音解决方案,开发者可以通过Media Foundation播放视频或声音文件、进行多媒体文件格式转码,或者将一连串图片编码为视频等等。

Media Foundation是DirectShow为主的旧式多媒体应用程序接口的替代者与继承者,在微软的计划下将逐步汰换DirectShow技术。Media Foundation要求WindowsVista或更高版本,不支持较早期的Windows版本,特别是WindowsXP。 

       此处既然是和MFGetStrideForBitmapInfoHeader接口,于是到MSDN上查看该接口的requirements(要求说明)。随便以一个常用的API函数和msdn为关键子,比如“GetWindowText msdn”,到网上搜索,进入msdn网页,然后再以MFGetStrideForBitmapInfoHeader函数名去搜素:

按上述步骤找到MFGetStrideForBitmapInfoHeader接口说明页面:

在MFGetStrideForBitmapInfoHeader函数的requirements部分看到,只有vista以上的系统才支持该接口,所以XP系统中没有,所以运行程序时就报错了。

2.3、为啥会报找不到MFGetStrideForBitmapInfoHeader接口

       有人可能会说,虽然代码中调用了MFGetStrideForBitmapInfoHeader接口,但实际运行不会执行到该接口的调用处(因为之前的函数的调用代码已经被删除掉),为啥还会报找不到这个接口呢?这个地方有个误区,并不是说,实际代码不会运行到就不检测,实际上只要代码中调用了其他库中的接口,不管程序是否会执行到,都会去做检测。

       有人可能会问,系统怎么知道要到MFPlat.dll库中去找MFGetStrideForBitmapInfoHeader接口的呢?是因为在编译代码时,这个接口是从MFPlat.dll库对应的.lib导入库中引入的,链接时会去检测能否链接到。在编译生成的二进制文件的PE信息中会有导入表,记录从哪些库中导入了哪些接口,而程序启动时会去读导入表中的信息,这样系统就知道了。

2.4、在两个XP系统中表现现象不太一样

        在客户XP系统上运行有问题,我们不能一直在客户机器上试错,我们需要在公司环境中找到XP环境去进行验证和测试。但现在基本都没人用XP了,很难找到装XP系统的机器了,后来我们找到了一台安装了XP虚拟机的机器。于是在该XP虚拟机系统中安装软件,安装完成后启动报错,如下:

这个报错和客户的XP系统中的报错有些不一样,在XP虚拟机中直接报找不到MFPlat.dll库,而在客户的XP系统中可以找到MFPlat.dll库,只是在MFPlat.dll中找不到MFGetStrideForBitmapInfoHeader接口。

       为啥两个都是XP系统,一个有MFPlat.dll库,一个没有MFPlat.dll库呢?可能客户的XP机器上之前安装了其他软件,向系统目录中拷贝了MFPlat.dll库。上面讲到Media Foundation时,明确不支持XP系统的,这个和MSDN上的函数说明也一致的。

2.5、此问题的解决办法

       这个问题的解决办法是,将Media Foundation相关的函数调用全部注释掉,这样就不会去链接和加载Media Foundation相关的库了。修改后重新编译版本,安装后启动程序就没问题了,程序可以正常启动起来了。

       其实这也暴露一个问题,我们的软件测试场景没有覆盖全,这点是有问题的,不能拿到客户环境中试错,应该在公司环境中进行充分全面的测试,要对多个系统进行兼容性测试。

3、程序执行某一操作时发生了线程卡死问题

       本以为上述问题解决了,就不再有问题了,结果在软件在执行某个常用的操作后就卡死了,整个UI界面卡死了,无法操作了!应该是UI线程出问题了!这个问题是必现的,于是重新启动程序,然后将Windbg附加到进程上,即使用Windbg去分析这个卡死的问题。

3.1、将Windbg附加到目标进程上初步分析卡死的原因

        挂上Windbg,复现问题,点击菜单栏Debug->Break,让Windbg中断下来。因为是UI界面卡死,UI界面属于UI主线程,对于UI程序来说,UI线程是线程列表中的0号线程,所以使用~0s命令切换到UI主线程,查看UI主线程的函数调用堆栈。

       切换到UI主线程之后,输入kn命令查看函数调用堆栈,果然卡住了,卡在ntdll!KiFastSystemCallRet函数调用处:

一直没返回!多次go,还是卡在这个函数上,该函数是从用户态转到内核态的,因为当前Windbg进行的用户态的调试,看不到内核模块的接口,应该是内核态卡死了,导致ntdll!KiFastSystemCallRet函数一直没返回,所以导致UI线程卡死了。

       从函数调用堆栈上看,当前的卡死是调用系统多媒体库winmm中的API接口mixerClose触发的。为啥会调用这个接口呢?因为程序需要获取系统的麦克风设备,会去调用mixerOpen接口,后面需要调用mixerClose将句柄关闭。

3.2、从动态调试的Windbg中导出dump文件,事后进行进一步分析

        为什么会出现卡死,需要对着C++源码进行详细分析了,于是使用.dump命令将当前进程的上下文导出到dump文件中:

.dump /ma D:\0512.dmp

然后将dump文件拿到我工作机器上,对着C++源码分析。

       在我机器上用Windbg打开这个dump文件,因为这个问题中函数卡住了,并没有发生C++异常或崩溃,所以不需要执行.excr命令。上面已经说过,问题发生在UI主线程,即0号线程,我们只需要使用~0s命令切换到UI线程,然后使用kn命令查看函数调用堆栈即可。

       由于此时Windbg没有加载pdb符号库文件,从现有堆栈中我们看不到具体的函数名称。于是使用lm命令查看函数调用堆栈中模块的时间戳,通过时间戳到文件服务器上找到对应时间点的pdb文件。比如:lm vm directui*:

找到pdb文件后,将pdb文件路径设置到Windbg中,然后再使用kn命令查看函数调用堆栈,看到了具体的函数接口,如下所示:

3.3、加载系统pdb文件后可能会看到更详细的函数调用堆栈

        此外,此处还可以设置Windows系统库pdb在线下载地址:

srv*f:\mss0616*http://msdl.microsoft.com/download/symbols

这样Windbg就会自动到这个服务器上去下载系统库对应版本的pdb文件了。其中http://msdl.microsoft.com/download/symbols,是微软系统库pdb文件下载服务器地址,然后f:\mss0616是本地下载系统pdb文件的存放路径。

       加载系统库pdb的好处是,可能能看到系统库中更详细的函数调用,在本例中设置系统库在线pdb下载地址后Windbg去自动下载系统库pdb,加载系统库的pdb后显示的系统库相关的调用堆栈要详细很多,如下:

在本问题中,函数调用堆栈相对于之前的看到的,要多出来几行,还能看到是调用了ntdll!ZwWaitForSingleObject去等待一个内核对象,于是调用ntdll!KiFastSystemCallRet进入内核态。

3.4、本问题的解决办法    

       引发上述问题的代码是以前为了辅助解决一个小问题而引入的,因为项目比较紧急,就没有深入地研究为什么会发生死锁,临时将相关的代码注释掉去临时解决这个问题。

4、总结

       在问题中积累,在问题中进步!在解决问题的过程中增长见识,积累经验!要多关注细节,多思考多总结,处理的问题多了,素材也就多了,积累和总结的也就多了!可以将以往的案例、知识点和经验串联起来,进行梳理和归纳,就能形成一套相对完整的知识体系和技能!

       这是多年来处理C++软件异常问题的最大的心得和体会,我这一路就是这么走过来的,通过历史的积累和总结,输出了实战型技术专栏《C++软件调试与异常排查从入门到精通系列教程》:
C++软件调试与异常排查从入门到精通系列教程https://blog.csdn.net/chenlycly/article/details/125529931希望专栏里总结的大量实战经验能帮助到大家。

       此外,积累的素材多了,写文章时就有大量的主题可写了;积累的素材多了,做技术分享和培训时就有很多实战案例去讲了。   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/553698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈元年方舟数据中台之标签管理平台

在现如今的大数据时代,相信大家一定了解或者听说过下列几个场景: 购物APP:千人千面,意思不同用户使用相关的产品感觉是不一样的,不同用户看到的购物APP首页推荐内容和其他相关推荐流信息可能是完全不同的。 社交APP&a…

【MySQL新手到通关】第一章 数据库概述

文章目录 1. 为什么要使用数据库2. 数据库与数据库管理系统2.1 数据库的相关概念2.2 数据库与数据库管理系统的关系 3. MySQL介绍3.1 概述3.2 关于MySQL 8.03.3 为什么选择 MySQL3.4 Oracle vs MySQL 4. RDBMS 与 非RDBMS4.1 关系型数据库4.1.1 实质4.1.2 优势 4.2 非关系型数据…

基于QEMU的RISC-V架构linux系统开发(二)——RISC-V的Linux内核移植

1.在国内linux镜像源(网易)linux内核稳定版本V5.15.73(注意:因为buildroot不支持最新版本,因此不下载最新版本)的版本源码,链接如下所示: http://mirrors.163.com/kernel/v5.x/ 图1…

Linux 常用远程连接工具你用过几个?

想必大家对linux不陌生,但是一提起如何远程连接它可能一头雾水,今天通过下面的几个工具来简单探讨一下常用的linux远程连接工具的使用,希望对你的日常使用有所帮助。 1、Xshell 介绍: xshell 是一个非常强大的安全终端模拟软件…

如何借助Kafka持久化存储K8S事件数据?

大家应该对 Kubernetes Events 并不陌生,特别是当你使用 kubectl describe 命令或 Event API 资源来了解集群中的故障时。 $ kubectl get events15m Warning FailedCreate …

c语言笔试题整理

1、请填写 bool , float, 指针变量 与 “零值” 比较的 if 语句。 提示:这里“零值”可以是0, 0.0 , FALSE 或者“空指针”。 例如int 变量n 与“零值”比较的if 语句为: if ( n 0 ) if ( n ! 0 ) 以此类推。 (1)请写出bool flag 与“零值…

陪诊系统源码|陪诊系统开发|陪诊小程序源码

随着医疗技术的不断发展,陪诊已经成为了一个非常普遍的现象。随之而来的,就是一款名为“陪诊小程序”的应用产品的诞生。这款小程序通过互联网技术来提供陪诊服务,包含了很多实用功能。下面,我们就来详细介绍一下陪诊小程序的功能…

【历史上的今天】5 月 22 日:Windows 3.0 发布;虚幻引擎诞生;《吃豆人》问世

整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来。 今天是 2023 年 5 月 22 日,在 1994 年的今天,知名中文论坛曙光 BBS 站开通。1994 年 4 月 20 日,建立在中科院和北京大学、清华大学之间的…

Spring 官方建议的在 Spring Boot 应用中如何做单元测试

Spring Boot 提供了丰富的测试功能,主要由以下两个模块组成: ● spring-boot-test:提供测试核心功能。 ● spring-boot-test-autoconfigure:提供对测试的自动配置。 Spring Boot 提供了一个 spring-boot-starter-test一站式启动…

springboot+vue私人健身与教练预约管理系统(源码+文档)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的私人健身与教练预约管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者&…

【Java】常见内存溢出OOM

文章目录 前言一、定义二、 为什么会OOM?三、JVM内存模型四、OOM常见类型4.1 java堆内存溢出4.2 方法区溢出4.3 JAVA虚拟机栈溢出 五、OOM分析--heapdump总结 前言 一、定义 内存溢出: out of memory,OOM,全称“Out Of Memory”&…

西门子S7-1200 PLC之间无线PROFINET通信

西门子S7-1200 PLC 使用Profinet通讯时,一个做Profinet IO控制器,一个做Profinet IO设备。一个Profinet IO控制器可以最多支持16个Profinet IO设备,Profinet通讯不使用通讯指令,只需要配置好数据传输地址,就能够实现数…

睿铂在广东,自然资源部经济管理科学研究所“多测合一”项目分享

引言 DG4 Pros倾斜摄影相机作为睿铂旗舰系列产品,它的硬件与软件配置都无愧于其顶级倾斜相机的称号。在它的帮助下,客户得以挑战很多以往受限于设备技术条件,实施起来非常困难的项目。 本次,自然资源部经济管理科学研究所&#…

App Store上线APP流程

现在App Store上已经有数百万款应用,因此对于App的规范要求也越来越高,对于新上线的APP需要满足这些规则并不是件容易的事。今天和大家分享这方面的知识,希望大家喜欢。北京木奇移动技术有限公司,专业的软件外包开发公司&#xff…

Mysql中存储引擎的区别及比较

MyISAM存储引擎 MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事务。 MyISAM主要特性有: 1、大文件(达到63位文件长度&#…

AI人工智能随机森林分类器的原理、优缺点、应用场景和实现方法

随机森林分类器(Random Forest Classifier)是一种常用的机器学习算法,它是基于决策树的一种集成学习方法。在人工智能(Artificial Intelligence,简称AI)领域中,随机森林分类器是一种高效的算法&…

艺术签名免费设计的方法分享,快来收下

在今天的数字时代,艺术签名已经成为一个流行的趋势。无论是在社交媒体上,还是在个人品牌推广中,艺术签名都是一个重要的元素。但是,对于很多人来说,设计一个独特的艺术签名可能需要付出昂贵的代价。然而,有…

flstudio21更新内容介绍FL水果2023旗舰版下载

昨天为大家展示了 FL STUDIO21 新增的插件,今天让我们看一看还有哪些新变化?FL Studio中文版惯称水果, 是一个完整的电音软件音乐制作环境或数字音频工作站。是现在流行的数字音频工作站之一,包括撰写,整理,记录,编辑,电音,混音和掌握专业品质的音乐。 0…

Open Ai 常见接口参数说明以及常见报错总结

📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言&#x1f4d…