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

从业务层的代码出发,去排查通用框架代码崩溃的问题

目录

1、问题说明

1.1、Release下崩溃,Debug下很难复现

1.2、用Windbg打开dump文件,发现崩溃在通用的框架代码中

2、进一步分析

2.1、使用IDA查看汇编代码尝试寻找崩溃的线索

2.2、在Windbg中查看相关变量的值

2.3、查看最近代码的修改记录,找到了引发问题的点

2.4、该问题中需要关注的点

3、问题总结

4、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N6B9https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N6B9https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)icon-default.png?t=N6B9https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N6B9https://blog.csdn.net/chenlycly/category_11931267.html       有时程序可能会崩溃在通用的框架代码中,但一般不是框架代码的问题,基本都是上层业务代码有问题导致的,框架代码中可能会引用业务层管理的业务类对象,如果引用的业务类对象有问题,则可能导致框架代码出异常。今天我们就来讲一个崩溃在通用框架代码中的实例,这个问题虽然比较简单,但有很多值得思考的细节,这个实例很有价值。下面详细讲述一下该问题实例的完整分析过程,以及有哪些值得思考的点与细节。

1、问题说明

       测试同事在测试新版本软件(Release版本)时,发现在执行某个常用的操作时会发生崩溃,且问题在测试PC机上是必现的,这个功能在前几天的版本中是没问题的。

1.1、Release下崩溃,Debug下很难复现

       最近,我们的开发人员在这个功能点上做了一些修改,新增了一些需求点,但开发人员在Debug下没有复现这个崩溃,一直查不出具体的原因。

       Debug下运行没问题,Release下运行有问题,这种现象我们之前也时不时的遇到。究其原因,可能是因为Debug下和Release下的内存管理分配机制是不一样的,Debug下会额外多分配一些内存存放调试信息。也有可能是变量未初始化引起的,Debug下会对变量自动进行初始化,比如:

* 0xcccccccc : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
* 0xcdcdcdcd : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory

Release下不会对变量内存进行初始化,变量的值会是分配内存时内存中残留的随机值。这些是引发程序在Debug下和Release下运行不同表现现象的常见原因。此外,也有可能测试场景有所不同,开发同事这边Debug下的场景和测试同事那边的Release下的场景有差异,所以表现出不同的现象。

1.2、用Windbg打开dump文件,发现崩溃在通用的框架代码中

       程序在发生崩溃时,程序中安装的异常捕获模块捕获到异常并自动生成了包含异常上下文信息的dump文件,测试同事让我帮忙分析一下这个问题。取来dump文件,用Windbg打开,使用.ecxr命令切换到发生异常的那个线程,然后使用kn命令查看崩溃时的函数调用堆栈,如下所示:

首先查看崩溃的那条汇编指令,汇编指令中访问了很小的内存地址,所以触发了内存访问违例,引发崩溃。像是空指针引发的,但有待于进一步确定。

       然后查看崩溃时的函数调用堆栈。和以往大部分崩溃有所不同,大部分时候函数调用堆栈中显示都是与崩溃有直接关系的业务层代码的函数调用,但这次堆栈中显示的是duilib开源库中的框架代码,和具体的业务层代码没有直接的关系,所以这个问题有着一定的隐蔽性。

       所以这个问题没法快速定位出来,并且我这边也有开发任务,没有多余的时间和精力去详细研究这个问题,于是只能让相关开发人员自行排查,想办法复现问题,并详细查看最近修改的代码,看看能否找到引发问题的点。 

2、进一步分析

       开发同事排查了,但始终找不到引发问题的代码。出问题的功能点是软件的主要功能点,一操作就崩溃,导致后续的很多功能点测试没法展开了。所以这个崩溃需要尽快解决,于是又把我拉过来,希望尽快将这个问题解决掉。

2.1、使用IDA查看汇编代码尝试寻找崩溃的线索

       函数调用堆栈都是框架中的代码,没法直接找到引发崩溃的线索,于是尝试使用IDA查看汇编代码上下文,看看为什么会产生崩溃。用IDA打开函数调用的堆栈中的模块文件,将汇编代码与C++源码对照起来看:

但看下来并没有找到有效的线索。

2.2、在Windbg中查看相关变量的值

       于是又在Windbg中尝试查看函数中相关变量的值,有时相关变量的值是排查问题的关键线索。查看CWindowWnd::__WndProc函数中相关变量的值,发现收到消息id为0xf,如下所示:

对应的消息为WM_PAINT消息(#define WM_PAINT   0x000f),为啥收到该消息会产生崩溃呢?

2.3、查看最近代码的修改记录,找到了引发问题的点

       当前出问题的这个功能点,不是我这边开发的,对相关的细节不清楚,于是让同事看svn上的修改记录,和他一起看都修改了哪些代码。

       当看到某个cpp的修改记录时,一眼看出了问题,相关代码片段如下所示:

程序在收到底层的某个消息时,会弹出一个提示框,这个提示框之前是模态的,后来应测试要求(模态框体验不好,要改成非模态的)将之改成非模态的。之前将模态框换成了非模态框,即本来是调用ShowModal显示模态框,后来改成调用ShowWindow接口显示非模态框。调用ShowModal接口时,窗口关闭时ShowModal才会返回,对应的函数中的局部变量窗口类对象CMicStateTipWnd dlg的生命周期和ShowModal接口一致,不会有问题。

       但改成ShowWindow后,窗口显示出来后,ShowWindow接口立即返回,这样就退出了当前函数,这样局部变量CMicStateTipWnd dlg的内存就自动释放了,但窗口已经创建出来了,窗口需要绘制,会产生WM_PAINT消息,就会进入到CWindowWnd::__WndProc静态函数中处理,就需要调用对应的窗口类CMicStateTipWnd对象,调用窗口类CMicStateTipWnd::HandleMessage去进行窗口的绘制刷新。但窗口类CMicStateTipWnd对象是局部变量,对象已经析构,内存已经释放引用已经释放内存的对象地址,所以就产生了崩溃。

2.4、该问题中需要关注的点

       这个地方有一点需要注意一下,特别是新人会容易混淆。

       窗口类CMicStateTipWnd对象在函数退出时自动析构销毁,但使用该类创建的窗口是不会跟着自动销毁的!窗口类对象的销毁是业务代码管理和控制的,而窗口创建成功后是操作系统管理的,窗口的销毁需要调用DestroyWindow去销毁,当然这是业务层去控制类对象与窗口的同步的!在这个问题中虽然窗口类CMicStateTipWnd对象析构了, 但窗口还在的,窗口会产生一些消息(比如本例中的WM_PAINT消息),这些消息会走到CWindowWnd::__WndProc静态函数中进行处理,当引用到CMicStateTipWnd对象,但对象已经析构了,所以导致内存访问违例,产生了崩溃!

3、问题总结

       本例中,程序崩溃在duilib界面库的框架代码中,这个通用框架用了很多年了,基本可以确定不是框架代码的问题,应该是上层业务代码的问题。在排查这类框架代码崩溃问题时,应该从上面的业务代码入手,要从业务层代码维护的窗口类对象入手,因为框架代码中会引用到业务层的类对象,如果业务层将类对象内存释放了,框架代码还访问该业务类对象,则会引发内存访问违例,引发崩溃。    

       虽然本例中涉及到的是UI界面框架,但项目代码中有使用了很多其他框架,这些框架代码可能也会出现类似的异常崩溃场景,所以对这个实例的排查思路及排查方法有参考意义。

       总之,如果程序崩溃在通用的框架代码中,一般不是框架的问题,基本都是上层业务代码的问题,应该从业务层代码入手,从框架中引用的业务层类对象入手(引用的业务层类对象是业务层维护和管理的)。比如,程序崩溃在QT库中,一般不是QT库有问题,基本都是上层业务代码的问题。再比如,崩溃在系统库或者C/C++运行时库中,不是系统库或运行时库有问题,一般都是上层业务代码有问题。可能是传入了不合法的参数,传入了不可访问的内存地址。

4、最后

        在编写代码时,要尽量考虑的全面一些,考虑尽可能多的场景,尽量将代码写的严谨缜密一点。遇到问题、排查问题时,一定要多关注细节,事后要进行积极的思考与总结。要搞清楚为什么会出问题以及问题是怎么解决的,对出问题的代码进行进一步或深入研究,要彻底搞清楚根源,这样下次再遇到类似问题代码时能快速做出反应!

       对于复杂的问题,事后要主动进行复盘,要搞清楚问题的来龙去脉(为什么会出这个问题?这个问题是如何解决的?),即便问题点所在的模块不是自己负责的,也要尽量去接触去了解。事后要积极地思考和总结,可以将以往遇到的一些问题给串联起来,将相关的知识点进行归纳,比如归纳出引发问题的常见原因积极常用的排查方法。

       细节出真知!要多关注细节,多提炼出一些值得关注和思考的点,甚至可以从一些看似简单的实例中找到一些有价值的点进行展开和总结。思考的多了,了解的技术细节和知识点就多了,可以总结的东西就越多,对一些编程问题与细节点理解的就更深刻了。在遇到新的问题时,就能在已取得的认知和积累的基础上做出快速反应,有更多更开阔的思路去排查问题。如果之前遇到的问题,后面又遇到了,或者遇到了类似的问题,依然是没有思路、没有头绪,不知从何查起,这就不应该了!

       对相关细节和编程点了解的更透彻后,能让我们在编写新的代码时能考虑的更加全面,在最开始编码时就能想到可能存在的潜在问题。

相关文章:

从业务层的代码出发,去排查通用框架代码崩溃的问题

目录 1、问题说明 1.1、Release下崩溃,Debug下很难复现 1.2、用Windbg打开dump文件,发现崩溃在通用的框架代码中 2、进一步分析 2.1、使用IDA查看汇编代码尝试寻找崩溃的线索 2.2、在Windbg中查看相关变量的值 2.3、查看最近代码的修改记录&#…...

LLM预训练大型语言模型Pre-training large language models

在上一个视频中,您被介绍到了生成性AI项目的生命周期。 如您所见,在您开始启动您的生成性AI应用的有趣部分之前,有几个步骤需要完成。一旦您确定了您的用例范围,并确定了您需要LLM在您的应用程序中的工作方式,您的下…...

[Machine Learning] 损失函数和优化过程

文章目录 机器学习算法的目的是找到一个假设来拟合数据。这通过一个优化过程来实现,该过程从预定义的 hypothesis class(假设类)中选择一个假设来最小化目标函数。具体地说,我们想找到 arg min ⁡ h ∈ H 1 n ∑ i 1 n ℓ ( X i…...

serialVersionUID 有何用途?如果没定义会有什么问题?

序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道,Java 对象是保持在 JVM 的堆内存中的,也就是说,如果 JVM 堆不存在了,那么对象也就跟着消失了。 而序列化提供了一种方案,可以让你在即使 JVM 停机…...

C# OpenCvSharp DNN 二维码增强 超分辨率

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp; using OpenCvSharp.Dnn; using OpenCvSh…...

this.$refs使用方法

深入理解和使用this.$refs——Vue.js的利器 Vue.js是一个流行的JavaScript框架,用于构建交互性强大的用户界面。在Vue.js中,this.$refs是一个强大的特性,允许你直接访问组件中的DOM元素或子组件实例。本教程将带你深入了解this.$refs的使用方…...

Ohio主题 - 创意组合和代理机构WordPress主题

Ohio主题是一个精心制作的多用途、简约、华丽、多功能的组合和创意展示主题,具有敏锐的用户体验,您需要构建一个现代且实用的网站,并开始销售您的产品和服务。它配备了最流行的WordPress页面构建器 WPBakery Page Builder(以前称为…...

mysql 、sql server trigger 触发器

sql server mySQL create trigger 触发器名称 { before | after } [ insert | update | delete ] on 表名 for each row 触发器执行的语句块## 表名: 表示触发器监控的对象 ## before | after : 表示触发的时间,before : 表示在事件之前触发&am…...

自然语言处理从入门到应用——LangChain:索引(Indexes)-[检索器(Retrievers)]

分类目录:《自然语言处理从入门到应用》总目录 检索器(Retrievers)是一个通用的接口,方便地将文档与语言模型结合在一起。该接口公开了一个get_relevant_documents方法,接受一个查询(字符串)并返…...

春秋云境:CVE-2022-0543(Redis 沙盒逃逸漏洞)

目录 一、i春秋题目 二、CVE-2022-0543:(redis沙盒逃逸) 漏洞介绍: 漏洞复现: 一、i春秋题目 靶标介绍: Redis 存在代码注入漏洞,攻击者可利用该漏洞远程执行代码。 进入题目:…...

关于uniapp组件的坑

关于uniapp组件的坑 我有一个组件写的没什么问题,但是报下面这个错误 is not found in path “components/xxx/xxxx” (using by “components/yyy/yyy”) 最后经过排除发现命名需要驼峰命名法 我原本组件命名: 文件夹名 test_tttt 文件名 test_tttt.vue 不行 最后改成文件…...

AIGC与软件测试的融合

一、ChatGPT与AIGC 生成式人工智能——AIGC(Artificial Intelligence Generated Content),是指基于生成对抗网络、大型预训练模型等人工智能的技术方法,通过已有数据的学习和识别,以适当的泛化能力生成相关内容的技术。…...

滑动验证码-elementui实现

使用elementui框架实现 html代码 <div class"button-center"><el-popoverplacement"top":width"imgWidth"title"安全验证"trigger"manual"v-model"popoverVisible"hide"popoverHide"show&quo…...

ubuntu 20.04 安装 高版本cuda 11.7 和 cudnn最新版

一、安装显卡驱动 参考另一篇文章&#xff1a;Ubuntu20.04安装Nvidia显卡驱动教程_ytusdc的博客-CSDN博客 二、安装CUDA 英伟达官网&#xff08;最新版&#xff09;&#xff1a;CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer CUDA历史版本下载地址&#xff1a;C…...

svg图片如何渲染到页面,以及svg文件的上传

svg图片渲染到页面的几种方式 背景&#x1f7e1;require.context获取目录下的所有文件&#x1f7e1;方式1: 直接在html中渲染&#x1f7e1;方式: 发起ajax请求&#xff0c;获取SVG文件 背景 需要实现从本地目录下去获取所有的svg图标进行预览&#xff0c;将选中的图片显示在另…...

GPT-LLM-Trainer:如何使用自己的数据轻松快速地微调和训练LLM

一、前言 想要轻松快速地使用您自己的数据微调和培训大型语言模型&#xff08;LLM&#xff09;&#xff1f;我们知道训练大型语言模型具有挑战性并需要耗费大量计算资源&#xff0c;包括收集和优化数据集、确定合适的模型及编写训练代码等。今天我们将介绍一种实验性新方法&am…...

深入理解ForkJoin

任务类型 线程池执行的任务可以分为两种&#xff1a;CPU密集型任务和IO密集型任务。在实际的业务场景中&#xff0c;我们需要根据任务的类型来选择对应的策略&#xff0c;最终达到充分并合理地使用CPU和内存等资源&#xff0c;最大限度地提高程序性能的目的。 CPU密集型任务 …...

Spring5学习笔记—AOP编程

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Spring专栏 ✨特色专栏&#xff1a; M…...

适用于 Docker 用户的 kubectl

适用于 Docker 用户的 kubectl 你可以使用 Kubernetes 命令行工具 kubectl 与 API 服务器进行交互。如果你熟悉 Docker 命令行工具&#xff0c; 则使用 kubectl 非常简单。但是&#xff0c;Docker 命令和 kubectl 命令之间有一些区别。以下显示了 Docker 子命令&#xff0c; 并…...

网络安全设备篇——加密机

加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密&#xff0c;从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据&#xff0c;如金融信息、个人身份信息等。 加密机的主要功能包括&#xff1a; 数据加密&#xff1a;加密机使…...

Rust 基础入门 —— 2.3.所有权和借用

Rust 的最主要光芒&#xff1a; 内存安全 。 实现方式&#xff1a; 所有权系统。 写在前面的序言 因为我们这里实际讲述的内容是关于 内存安全的&#xff0c;所以我们最好先复习一下内存的知识。 然后我们&#xff0c;需要理解的就只有所有权概念&#xff0c;以及为了开发便…...

Node.js-Express框架基本使用

Express介绍 Express是基于 node.js 的web应用开发框架&#xff0c;是一个封装好的工具包&#xff0c;便于开发web应用&#xff08;HTTP服务&#xff09; Express基本使用 // 1.安装 npm i express // 2.导入 express 模块 const express require("express"); // 3…...

阿里云通用算力型u1云服务器CPU性能详细说明

​阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff…...

设计模式之创建者模式

文章目录 一、介绍二、应用三、案例1. 麦当劳11随心配2. 代码演示3. 演示结果 四、优缺点五、送给读者 一、介绍 建造者模式(Builder Pattern)属于创建型设计模式&#xff0c;很多博客文章的对它的作用解释为用于将复杂对象的创建过程与其细节表示分离。但对于初学者来说&…...

Java之包,权限修饰符,final关键字详解

包 2.1 包 包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术&#xff0c;不同的技术类放在不同的包下&#xff0c;方便管理和维护。 在IDEA项目中&#xff0c;建包的操作如下&#xff1a; 包名的命名规范&#xff1a; 路径名.路径名.xxx.xxx // 例如&#xff…...

“深入解析JVM:Java虚拟机内部原理揭秘“

标题&#xff1a;深入解析JVM&#xff1a;Java虚拟机内部原理揭秘 摘要&#xff1a;本文将深入探讨Java虚拟机&#xff08;JVM&#xff09;的内部原理&#xff0c;包括JVM的架构、运行时数据区域、垃圾回收机制以及即时编译器等重要组成部分。通过对JVM内部原理的解析&#xf…...

Mac下Jmeter安装及基本使用

本篇文章只是简单的介绍下Jmeter的下载安装和最基本使用 1、初识Jmeter 前一段时间客户端app自测的过程中&#xff0c;有偶现请求某个接口返回数据为空的问题&#xff0c;领导让我循环100次请求这个接口&#xff0c;看看有没有结果为空的问题。听同事说有Jmeter的专业测试工具…...

云计算与边缘计算:加速数字化转型的关键驱动力

云计算和边缘计算技术正以惊人的速度改变着企业的业务和基础架构。这些先进的技术为企业带来了灵活性、可扩展性和成本效益的优势&#xff0c;重新定义了业务运作的方式。 云计算是通过互联网将计算资源提供给用户的一种服务模式。通过云计算&#xff0c;企业可以将应用程序、…...

TheGem主题 - 创意多用途和高性能WooCommerce WordPress主题/网站

TheGem主题概述 – 适合所有人的TheGem 作为设计元素、样式和功能的终极 Web 构建工具箱而设计和开发&#xff0c;TheGem主题将帮助您在几分钟内构建一个令人印象深刻的高性能网站&#xff0c;而无需触及一行代码。不要在编码上浪费时间&#xff0c;探索你的创造力&#xff01…...

Pytorch-day10-模型部署推理-checkpoint

模型部署&推理 模型部署模型推理 我们会将PyTorch训练好的模型转换为ONNX 格式&#xff0c;然后使用ONNX Runtime运行它进行推理 1、ONNX ONNX( Open Neural Network Exchange) 是 Facebook (现Meta) 和微软在2017年共同发布的&#xff0c;用于标准描述计算图的一种格式…...

天津网站建设优选企业/微信搜一搜怎么做推广

PHP 能够创建、打开、读取、写入、删除以及关闭服务器上的文件 PHP 能够接收表单数据 PHP 能够发送并取回 cookies PHP 能够添加、删除、修改数据库中的数据 PHP 能够限PHP1.CN中文网是国内最大的PHP资源分享技术交流为主的PHP专业网站&#xff0c;也提供了PHP中文博客&#xf…...

布料市场做哪个网站好/百度账号登录入口

慕少森stdio.h 哪些 是 头文件&#xff0c;里面包含一些常用的 函数例如 stdio.h里面有 scanf();printf()这些函数&#xff0c;没有stdio就不能用这些函数在C语言家族程序中&#xff0c;头文件被大量使用。一般而言&#xff0c;每个C/C程序通常由头文件(header files)和定义文件…...

网站建设测试验收报告/泰州seo网站推广

从2016年1月开始写博客&#xff0c;默默地更新《Spring Boot系列教程》&#xff0c;从无人问津到千万访问&#xff0c;作为一个独立站点&#xff08;http://blog.didispace.com&#xff09;&#xff0c;相信只有那些跟我一样&#xff0c;坚持维护自己独立博客的童鞋才能体会这有…...

广安建设局网站/企业网站建站模板

在做分类时常常需要估算不同样本之间的相似性度量(Similarity Measurement)&#xff0c;这时通常采用的方法就是计算样本间的“距离”(Distance)。采用什么样的方法计算距离是很讲究&#xff0c;甚至关系到分类的正确与否。 本文的目的就是对常用的相似性度量作一个总结。 本文…...

长沙设计公司排行/百度信息流优化

使用SQL从AWR收集数据库性能变化趋势 为了对数据库一段时间的性能情况有个全面了解&#xff0c;显然AWR是一个非常有用的工具&#xff0c; 但很多人只会在数据库有性能问题时才会生成问题时段的awr报告去分析。虽然AWR 中给出的统计数据是一段时间的&#xff0c;对于峰值情况把…...

嵌入式软件开发技术/厦门百度快速优化排名

偶然的机会&#xff0c;发现了B站的点歌机器人&#xff0c;觉得挺好玩的就自己做了一个简易版点歌机器人&#xff0c;预览如下&#xff1a; 功能 使用websocket&#xff0c;支持多人同时点歌&#xff0c;发送弹幕聊天具有搜索suggestion&#xff0c;用户体验更佳点击mv视频右上…...