您现在的位置是:首页 >技术杂谈 >为什么要学习C++软件调试技术?掌握调试技术都有哪些好处?网站首页技术杂谈
为什么要学习C++软件调试技术?掌握调试技术都有哪些好处?
目录
1.2、通过查看日志和代码去排查异常崩溃问题,费时费力,很难定位问
1.5、为了应对软件在不同环境中出现的各式各样的问题,我们需要掌握足够多的调试排查技术
1.6、掌握高效的调试分析技术,既能提升个人能力,也能体现个人价值
3.3、排查问题多了,见识和经验就多了,处理新问题就更加得心应手了
3.4、在排查问题的过程中,可以主动地去发掘学习的机会,去扩充自己的视野
3.6、通过排查问题去积累素材,可以用到日常的技术分享与培训中
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 通过技术分享和线下交流发现,很多C++开发人员在C++软件调试技术这一块比较欠缺,无论是刚毕业的新手,还是工作多年的老员工。这里面有个人的原因,也有环境的因素。考察一个软件开发人员的水平,一是要看编码与架构设计能力,二是要看软件调试能力。高水平的软件调试能力在处理项目上线后遇到的各式各样问题时显得尤为重要。今天我们就来详细讲一讲为什么要学习C++软件调试技术,以及学习C++软件调试技术有哪些好处。
1、为什么要学习C++软件调试技术?
在项目上线后,为了有效地应对客户使用软件过程中遇到的各式各样的问题,我们需要掌握多种软件调试手段和方法,要掌握排查软件异常问题的技巧,仅仅依靠单一的方式或手段是远远不够的。
1.1、IDE调试手段虽必不可少,但还不够
我们在项目初期的开发联调阶段,会使用IDE工具对代码进行Debug调试,将软件的基本流程和功能调通。由于Debug和Release下存在差异(比如变量是否会自动初始化及内存管理上的差异),有些问题只出现在Release版本中,在Debug下是没有的,这类问题没法通过Debug调试去排查的。
对于有些好复现的问题,我们可以进行Release下的调试。此外,除了直接的Debug和Release下的调试,还可以进行附加到进程调试。附加到进程调试,对于调试底层的单个模块是很好用的。
IDE调试是我们处理问题的最直接、最基本的手段,但IDE调试不能覆盖所有的场景,比如产品进入测试或发布上线后,有些问题是很难复现的,,所以没法通过Debug和Release调试去排查。
此外,产品上线到客户环境后遇到了问题,某些问题与客户的环境有着直接的关系,即只在客户端环境中才有问题。可能是客户的网络环境、系统版本或特殊的硬件配置导致的,问题只在客户的环境中出现,在我们厂商的内部测试环境中很难复现,像这类问题就不好去进行代码调试了,基本不可能到客户的环境中去调试代码的。所以仅仅依靠IDE调试去排查问题,是远远不够的。
1.2、通过查看日志和代码去排查异常崩溃问题,费时费力,很难定位问
为了排查软件在运行过程中遇到的问题,们会在软件中添加大量的打印日志,软件的运行日志是我们排查问题的重要手段。
软件中的异常主要包括两大类:业务逻辑上的异常和软件异常崩溃。
对于业务上的异常,可以通过打印日志去排查,通过运行日志去查看软件的运行流程和执行轨迹,还可以将相关变量的值打印出来,根据变量的值去辅助分析。此外,对于某些场景,还需要使用抓包工具去抓网络包分析。
对于软件异常崩溃,在排查手段与方法上,与业务上的异常排查有很大的不同,一般仅通过日志打印去排查崩溃问题,是很难定位的。因为日志中没法找到软件的崩溃点,很难找到引发软件崩溃的线索。
日志不是排查软件异常崩溃的主要手段,日志仅仅起到辅助的作用,比如我们在找到软件崩溃点及崩溃时的函数调用堆栈后,可以通过日志去查看代码的运行流程与执行轨迹,以及相关变量值去辅助分析引发崩溃的原因。
1.3、有的问题很难复现,可能只在客户的环境才能复现
有的软件异常问题很难复现,可能只在客户的网络环境或者PC机器的软硬件环境中才能复现。对于这类问题,一般我们需要使用多种手段和方法去排查,没法通过IDE调试去解决。
如果软件有捕获到异常,生成了包含异常上下文的dump文件,我们可以取来dump文件用Windbg或gdb等调试器进行分析。如果没有生成dump文件或者dump文件中看不到有效的信息,一般需要使用调试器到客户环境中进行动态调试,尝试去捕获有效的异常信息。
但在客户的机器上去动态调试有诸多的不便,比如问题很难复现,需要很多的时间去复现,这样就会耽误客户很多的时间。有些安全等级比较高的涉密客户,是不允许在其机器上安装Windbg调试器等软件的。
所以有时我们可以尝试在我们公司的环境中去复现问题,可能在长时间的拷机后可能会复现。在公司环境中复现问题,排查起来就方便很多了。
1.4、开发联调工期有限,必须在短时间内快速定位并解决问题
当项目处于功能联调阶段,发生异常崩溃处的代码很关键,是业务流程的必经之处,此处出问题,这块业务就没法继续联调了,如果项目工期有限,不能在这个问题上耗费太多的时间,需要尽快排查出来。
还有一种场景,为了项目竞标(打标),需要在一两天或较短时间内开发出一个新功能,时间非常有限,如果在测试时遇到异常崩溃,需要快速解决问题。
对于上述场景下的问题,需要使用多种分析手段和技巧去快速地定位。
1.5、为了应对软件在不同环境中出现的各式各样的问题,我们需要掌握足够多的调试排查技术
为了应对软件在不同环境中出现的各式各样的问题,对问题做出快速的响应,我们要系统地了解引发软件异常的常见原因,要知悉一些常用问题排查的手段与方法,要熟练使用各种常用的分析工具和调试工具去排查。对于一些复杂的问题,需要将多种方法和手段结合起来,使用多种工具去联合分析。
但掌握这些知识和技能不是一撮而就的事情,需要脚踏实地来学习,然后把学到的东西应用到实际的项目中,要多动手多实践,在问题中取得进步,在问题中积累经验。
1.6、掌握高效的调试分析技术,既能提升个人能力,也能体现个人价值
掌握高效的调试分析技术后,可以处理各式各样的软件疑难问题,在处理问题的过程中个人能力和经验都能得到有效地提升,可以积累大量的问题排查素材,可以形成一套完整的技能体系。具备别人不具备的软件调试能力,能解决别人搞不定的问题,这样能更好地体现出对企业的价值,这同时也是个人价值的体现。
2、C++软件调试技术的主体内容
通过大量的项目实战总结出来的C++调试技术的主要内容如下:
这个地方我就不再赘述了,C++调试技术的详细内容可以去查看专栏《C++软件调试与异常排查从入门到精通》:
3、掌握C++软件调试技术都有哪些好处?
系统地掌握软件调试技术之后,最直接的好处就是能高效地排查项目中遇到的各式各样难题,下面我们来看看都有哪些具体的好处。
3.1、在了解引发异常的常见原因后,在编写代码时更小心
在系统地了解引发C++软件异常的常见原因之后,能让我们在编写代码时考虑的更加谨慎、更加全面,从编码阶段就把一些潜在的问题给规避掉,将问题扼杀在摇篮中。
3.2、汇编语言接触的多了,能更好地理解软件底层的运行机制
有时我们在排查软件异常时,特别是在缺乏pdb符号库文件时,我们需要用IDA查看相关二进制文件的汇编代码上下文去辅助分析。
软件崩溃一般是崩溃在某条汇编指令上,查看汇编代码才能看出为什么会崩溃,可以查看汇编代码去辅助分析发生崩溃的原因。汇编代码熟悉了,就能更好地理解C++程序在CPU中是如何运行的,就能理解很多编程中之前理解不了的问题。
熟悉汇编代码,不仅可以辅助排查C++软件异常问题,还可以理解很多高级语言不好理解的编程细节(从汇编代码的角度可以看到代码的完整执行细节)!汇编代码才能最直接、最本真地反映出具体的细节!很多高级语言难以理解的编程点和细节,从汇编的角度去看,要好理解很多!
比如在《Windows核心编程》一书中,在第八章讲到多线程同步时,有个典型的多线程操作一个全局变量的实例,相关代码如下:
// define a global variable
long g_x = 0;
DWORD WINAPI ThreadFunc1(PVOID pvParam)
{
g_x++;
return 0;
}
DWORD WINAPI ThreadFunc2(PVOID pvParam)
{
g_x++;
return 0;
}
上述代码中,定义了一个long型的全局变量,然后创建了两个线程,线程函数分别是ThreadFunc1和ThreadFunc2,这两个线程函数中均对g_x变量进行自加操作(在访问共享变量g_x时未加锁同步)。在两个线程函数执行完后,g_x的值不一定为2。这个实例需要从汇编代码的角度去理解,从C++角度则不好理解,这是一个从汇编代码去理解代码执行细节的典型实例。
这个实例中对g_x进行自加的代码:
g_x++;
对应的汇编代码为:
MOV EAX, [g_x] // 将g_x变量的值读到EAX寄存器中 INC EAX // 将EAX中的值执行自加操作 MOV [g_x], EAX // 然后将EAX中的值设置到g_x变量内存中
关于这一实例的详细解读,后面我会专门写一篇文章去阐述,此处就不再展开了。
3.3、排查问题多了,见识和经验就多了,处理新问题就更加得心应手了
排查的问题越多,见识就越多,积累的经验就越多,这样在排查新的问题时手段就更多,思路会更加开阔,更加得心应手,定位问题的速度会更快。
3.4、在排查问题的过程中,可以主动地去发掘学习的机会,去扩充自己的视野
不要将自己局限在自己负责的那些模块中,从其他人负责模块问题中也能发掘一些学习的机会。比如在和兄弟组一起联调排查问题时,在帮他们排查他们负责模块的异常崩溃时,可以查看到他们开发组的代码,可以了解他们代码中好的设计思想。也可以了解到他们模块中的业务流程,对把握整个系统的业务流程有很大的促进作用。还可以捣鼓捣鼓他们经常使用的一些分析工具。
我们在日常工作中,要积极主动地发掘这样的学习机会,这些能有效地扩充我们的视野和认知。
3.5、在问题中进步,在问题中总结
排查问题的过程,是不断积累经验的过程,是技术取得不断进步的过程!
在问题排查出来后,要积极进行思考和总结,进行一些扩散性的延伸与归纳。通过项目实战,能学到很多通过经过实战检验的细节点,能搞懂以前学习时无法理解的知识点,能有效地扩充自己的认知范围,对一些要点能有更进一步的理解和认识。通过不断的思考与总结,可以形成一套属于自己的完整知识体系。比如我的技术总结专栏《C++软件调试与异常排查从入门到精通》就是通过大量的问题排查实战总结出来的一套完整的知识体系:
C++软件调试与异常排查从入门到精通专栏https://blog.csdn.net/chenlycly/article/details/125529931https://blog.csdn.net/chenlycly/article/details/125529931
1)通过回顾之前排查的诸多异常问题,回看引发这写问题的具体原因,总结出了《C++软件异常的常见原因分析与总结》一文:
C++软件异常的常见原因分析与总结https://blog.csdn.net/chenlycly/article/details/124996473https://blog.csdn.net/chenlycly/article/details/1249964732)通过回想很多异常问题的排查过程及排查方法,总结出了《排查C++软件异常的常见思路与方法》一文:
排查C++软件异常的常见思路与方法https://blog.csdn.net/chenlycly/article/details/120629327https://blog.csdn.net/chenlycly/article/details/1206293273)根据使用Visual Studio调试程序的一系列实战经验,总结出了《Visual Studio高效调试手段与技巧总结》一文:
Visual Studio高效调试手段与技巧总结https://blog.csdn.net/chenlycly/article/details/124884225https://blog.csdn.net/chenlycly/article/details/1248842254)根据排查问题时遇到的各种内存错误,总结出了《引发C++程序内存错误的常见原因分析与总结》一文
引发C++程序内存错误的常见原因分析与总结https://blog.csdn.net/chenlycly/article/details/128599525https://blog.csdn.net/chenlycly/article/details/128599525
专栏《C++软件调试与异常排查从入门到精通》还有很多其他的文章,感兴趣的可以去专栏中看,这个地方我就不再逐一展开了。
3.6、通过排查问题去积累素材,可以用到日常的技术分享与培训中
在排查问题的过程中,可以将dump文件、pdb文件和相关代码截图等作为案例素材保存下来,以方便以后去查看,也可以为后面的技术分享与培训积累大量的案例和素材。有大量实战案例的技术分享,内容会更加丰富,更加具有实战性。
4、学习软件调试技术的经历与心得分享
最近几年一直在负责部门的C++软件异常排查的工作,处理了成百上千个软件异常问题,正是通过这些问题的项目实战,积累了大量的经验,并做了详细的文字归纳与总结。《C++软件调试与异常排查从入门到精通》技术总结专栏,正是通过大量的项目实战总结整理出来的:
C++软件调试与异常排查从入门到精通专栏https://blog.csdn.net/chenlycly/article/details/125529931https://blog.csdn.net/chenlycly/article/details/125529931专栏中的内容都是通过项目实战总结出来的实战经验,有很大的实战参考价值,感兴趣的可以去详细看一看!
4.1、学习软件调试技术经历分享
多年前刚参加工作时,在开发过程中遇到软件异常崩溃时,因为缺少经验,排查起来会非常吃力,排查问题的手段和方法很有限,甚至会因为无法及时找出问题影响到开发进度,当时深深地体会到了在C++软件调试方面的不足,并从那时候开始对C++软件调试技术产生了浓厚的兴趣。于是开始系统地学习软件调试方面的技术知识,动手捣鼓一些常用分析工具:
并坚持把这些知识和工具应用到日常的项目中去。
在学习与应用的过程中,同事们也给予了大量的指导与帮助,特别是负责软件异常排查的同事给我分享大量的实战经验。也主动地学习其他同事常用的软件分析工具。就这样逐渐敲开了C++软件调试的大门,逐步承担起了部门C++软件项目中各种异常崩溃的排查工作。
此外,在邀请公司技术专家排查项目难题时,很珍惜这些难得的学习机会。在专家排查问题的故过程中,时刻关注他们排查问题的细节,跟着专家后面也学到了很多平时学不到的分析经验,以及一些高效的分析工具。一边学习,一边排查问题,一边积累经验。
对于一些典型的、有代表性的问题,事后会进行完整的复盘,在脑海中重现问题的诸多细节,搞清楚问题的来龙去脉,并对相关的技术点进行总结与进一步的思考。即便问题出在别的开发组的模块中,也会主动地帮忙排查,查看他们模块的代码,把问题给搞清楚。在这个过程中,不仅了解了底层模块的相关代码的设计思想和业务逻辑,还积累了大量的问题场景和素材,为后期的全面总结做好了大量的知识储备。
4.2、做技术分享的一些心得
通过几年的软件异常排查项目实战,对C++软件调试与异常排查技术进行了系统地总结,并开始对外输出这方面的技术内容。在公司范围内开始做C++软件调试技术的分享与培训,在培训和交流的过程中发现很多C++程序员在软件调试这一块比较欠缺,无论是刚毕业的年轻人,还是工作多年的老程序员。这其中有一些个人的原因,也有一些环境认知的原因。
开发人员调试能力比较弱,可能有环境的原因,可能也有个人的原因。可能工作环境中同事们很少使用专用的调试器和分析工具去排查问题,无法接触到系统的调试技术。还有一种可能,工作环境中有些同事会系统地使用调试技术去解决问题,并在部门或者小组中做过详细的技术分享,大家也有去听课学习,但大部分人都是三分钟热度,根本没有认真学,没有坚持下去,没有主动将所学的内容用到工作实践中去。学习技术,就是要投入大量的时间和精力,要不断的捣鼓和实践,把技术用到工作实践中去才能学出个样子的!
一门技术的学习,是需要不断的努力和不懈的折腾的,我们需要把手动起来,把所学的应用到工作实践中去,在学习中持续实践,在实践中持续学习!在我们漫长的职业生涯中,正是通过很多小事件从量变到质变,去实现技术的提升。