建站公司兴田德润在哪里,网站页面排版,现在做网站怎么赚钱,专业网络推广目录
1、问题说明
1.1、Release下崩溃#xff0c;Debug下很难复现
1.2、用Windbg打开dump文件#xff0c;发现崩溃在通用的框架代码中
2、进一步分析
2.1、使用IDA查看汇编代码尝试寻找崩溃的线索
2.2、在Windbg中查看相关变量的值
2.3、查看最近代码的修改记录#…目录
1、问题说明
1.1、Release下崩溃Debug下很难复现
1.2、用Windbg打开dump文件发现崩溃在通用的框架代码中
2、进一步分析
2.1、使用IDA查看汇编代码尝试寻找崩溃的线索
2.2、在Windbg中查看相关变量的值
2.3、查看最近代码的修改记录找到了引发问题的点
2.4、该问题中需要关注的点
3、问题总结
4、最后 VC常用功能开发汇总专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/125529931C软件分析工具从入门到精通案例集锦专栏文章正在更新中...https://blog.csdn.net/chenlycly/article/details/131405795C/C基础与进阶专栏文章持续更新中...https://blog.csdn.net/chenlycly/category_11931267.html 有时程序可能会崩溃在通用的框架代码中但一般不是框架代码的问题基本都是上层业务代码有问题导致的框架代码中可能会引用业务层管理的业务类对象如果引用的业务类对象有问题则可能导致框架代码出异常。今天我们就来讲一个崩溃在通用框架代码中的实例这个问题虽然比较简单但有很多值得思考的细节这个实例很有价值。下面详细讲述一下该问题实例的完整分析过程以及有哪些值得思考的点与细节。 1、问题说明 测试同事在测试新版本软件Release版本时发现在执行某个常用的操作时会发生崩溃且问题在测试PC机上是必现的这个功能在前几天的版本中是没问题的。
1.1、Release下崩溃Debug下很难复现 最近我们的开发人员在这个功能点上做了一些修改新增了一些需求点但开发人员在Debug下没有复现这个崩溃一直查不出具体的原因。 Debug下运行没问题Release下运行有问题这种现象我们之前也时不时的遇到。究其原因可能是因为Debug下和Release下的内存管理分配机制是不一样的Debug下会额外多分配一些内存存放调试信息。也有可能是变量未初始化引起的Debug下会对变量自动进行初始化比如 * 0xcccccccc : Used by Microsofts C debugging runtime library to mark uninitialised stack memory * 0xcdcdcdcd : Used by Microsofts 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、最后 在编写代码时要尽量考虑的全面一些考虑尽可能多的场景尽量将代码写的严谨缜密一点。遇到问题、排查问题时一定要多关注细节事后要进行积极的思考与总结。要搞清楚为什么会出问题以及问题是怎么解决的对出问题的代码进行进一步或深入研究要彻底搞清楚根源这样下次再遇到类似问题代码时能快速做出反应 对于复杂的问题事后要主动进行复盘要搞清楚问题的来龙去脉为什么会出这个问题这个问题是如何解决的即便问题点所在的模块不是自己负责的也要尽量去接触去了解。事后要积极地思考和总结可以将以往遇到的一些问题给串联起来将相关的知识点进行归纳比如归纳出引发问题的常见原因积极常用的排查方法。 细节出真知要多关注细节多提炼出一些值得关注和思考的点甚至可以从一些看似简单的实例中找到一些有价值的点进行展开和总结。思考的多了了解的技术细节和知识点就多了可以总结的东西就越多对一些编程问题与细节点理解的就更深刻了。在遇到新的问题时就能在已取得的认知和积累的基础上做出快速反应有更多更开阔的思路去排查问题。如果之前遇到的问题后面又遇到了或者遇到了类似的问题依然是没有思路、没有头绪不知从何查起这就不应该了 对相关细节和编程点了解的更透彻后能让我们在编写新的代码时能考虑的更加全面在最开始编码时就能想到可能存在的潜在问题。