首页 > 其他分享 >关于修Bug的一些想法

关于修Bug的一些想法

时间:2022-08-30 22:45:27浏览次数:54  
标签:想法 Bug 问题 线程 关于 堆栈 UML bug

0. 前言

八月份快要结束了,这个月也没有啥输出,今天下班较早,赶一篇学了一年多C++后的一些思考,关于修Bug的一些想法和思路。
平时工作中,如果写代码花费一天时间,那调试解决Bug可能有时候会花好几天、或许更长。此外,线上部署的服务如果出现崩溃或者返回异常的问题,也会反馈给相应的开发负责人,毕竟自己挖的坑要自己填。大多数情况下,如果框架稳定且没有新需求开发,很多Bug就只是某些业务代码导致的小问题,也很好定位,但说实在的,长期写业务代码、一堆if else逻辑对个人能力提升很有限。如果想要学更深入的技术,还是要多写一些框架层面、算法设计方面的代码,不如如何设计多个类之间的调用关系、如何用基本数据结构组织一个适用于业务逻辑的结构体或者class。扯远了,这里只说一下我是如何在工程中调试分析bug的方法。

这里只说C++工程,其他语言的话也大同小异。首先,一个C++工程从0到1的实现流程一般流程是:①确定业务需求,即会提供什么样的输入,期望什么样的输出。后端C++工程一般向外提供的其实是一个类库,类库在运行期间的作用犹如一个函数,依据传入的数据流,做一些逻辑复杂的计算,然后返回出来一个结果数据流或者多个数据流。②基于需求,整理出详细的数据流图,即若要从输入数据计算出输出数据的话,需要经过哪几个步骤;③设计UML图。将上一步的数据流图转化为UML图,UML图不是单纯的将数据流图搬过来,这里面粒度要细到每个类及其public接口才可以。同时也要表明类之间的关系,主要有继承、实现、组合、聚合、关联、和 依赖这六种关系。之后就是④按照UML图进行相应实现,实现的时候也要注意,接口类单独在include文件夹内,实现类如果实现很庞大,一般也是要以同名的.cc和.h来组织,并置于源文件夹(src或source文件夹)下的对应模块内、具体嵌套多少级由类的作用域确定。当然如果某些类不需要虚接口类或者作用范围很小,那么也没有必要设置include内的头文件。

1. 如何修Bug

说上面这些,主要是想说,Bug就是在按照UML图写代码的时候引入的,这有可能是UML图设计的本来就有问题,比如会有调用纯虚函数的问题,这就是UML图的问题,或者说是类的实现问题。但实际开发中,也没有说非要先创建UML图作为参考来写代码,但我认为这是必要的,尤其是对于框架比较复杂的工程。

  • 通常遇到的Bug可以分为两类,一种是编译期就能报出来的,另一种是运行期出现的。编译期的Bug都是小问题,常见的就是只有声明没有定义导致链接失败、也有可能是重复定义导致二义性,这些问题可能是头文件没有引入或者重复引入头文件导致,也有可能是其他问题,但编译期大多数bug只需要关注报错位置直接相关的地方即可,同时也要明确编译过程是以每个cpp文件为基本编译单元的,从这一点出发,可以分析很多编译问题。

  • 第二种:运行期bug,这里我们只谈导致崩溃的bug,其实所有没有按照预期运行的异常动作或结果都可以称为bug,崩溃最常见的就是segmentation fault,当然还有其他各种各样的崩溃。工程一般都有log模块,第一步先查看日志,找找有价值的信息,说不定就直接找到问题了。此外,既然是运行期bug,那么最好调试运行起来看看究竟发什么什么错误。这就是运行期bug修复的第二步:bug复现,而且最好是最小复现,即能够在测试代码启动后最快时间复现出问题,毕竟可能要调试很多次,缩短复现时间是十分必要的。第三步:在崩溃现场查看堆栈。这里我还是建议使用IDE调试,堆栈看起来比较方便,可以摁鼠标跳转到对应源码,比命令行gdb调试方便。先在工程代码的最底层那层查找问题,因为再往下是标准库了,标准库一般是不会出错的。第四步:修复bug。比如一个越界访问bug,在越界访问的那层堆栈找到问题,但导致崩溃的原因可能并不在那儿,你可能需要在堆栈上层找找,确定这个变量是从哪里赋值的,在最合适的地方加以保护或其他处理方式来修复问题。对于多线程运行的程序,就不太好调了,可能需要分析更多的地方。

  • 此外,工程运行过程中可能出现卡死的情况,这种问题在多线程工程中出现的情况较多,而且还不好复现。这种问题最好是保护现场,然后attach到对应进程查看堆栈信息,看看是卡在哪里,是不是所有线程阻塞导致的。还有一种情况是死循环,这种情况表面上看是卡死,但你去监控cpu的时候,能发现cpu利用率是较高的,而且一般都是100的整数倍,表明有几个线程在死循环一直跑的状态,这种情况也是看堆栈就能发现问题。比较大的多线程工程查看threads是有成百上千线程的,在这里面优先去看那些条件变量阻塞的线程而不是那些系统拉起来的线程,条件变量阻塞的线程阻塞的原因也大概率不是在本线程,而是其他线程没有按预期发出唤醒信号导致的。

  • 还有,内存泄漏。这种问题如果不能通过分析源码找到的话,一般是用valgrind或asan这类工具分析,我习惯于用valgrind,但不一定能找到,只能是作为一个缩小排查范围的参考。

总之,编译期间的bug,都是小问题,主要还是对编译原理理解要到位,另外养成良好的工程组织习惯,形成自己的风格,可以避免大多数这类问题。另外,c++工程我们一般用cmake构建,所以cmake也要掌握,有些东西是需要在cmake文件里面设置的;而运行期bug,就是通过分析堆栈找问题,原因千奇百怪,不然要那么多程序员干嘛。

标签:想法,Bug,问题,线程,关于,堆栈,UML,bug
From: https://www.cnblogs.com/lee-zq/p/16640881.html

相关文章

  • 关于vi不正常退出产生的swp文件
    关于vi不正常退出产生的swp文件_lingdxuyan的博客-CSDN博客_linux如何删除swp文件 https://blog.csdn.net/lingdxuyan/article/details/4993868非正常关闭vi编辑器时会......
  • 线程池中的一个 BUG,注意了!!
    来源:https://segmentfault.com/a/1190000021109130问题描述前几天在帮同事排查生产一个线上偶发的线程池错误逻辑很简单,线程池执行了一个带结果的异步任务。但是最近有......
  • 关于 JavaScript 函数的思考
    函数可以将一堆重复的代码整合成一个整体,在需要改变的地方通过参数传值来改变。比如,根据类型查询数据,接口返回的数据一样,后续处理这个数据的逻辑也是一样的,只有类型和输入......
  • 《关于程序猿也得刷行测题的这一天》——第一章:理想与现实
    别人一谈到程序员,都以为是上天入地,无所不能,代码在他们的手中就像花一样。大到可以把大道都给磨灭的量子计算机,小到可以随手修好邻居老王家的路由。就差不能送全体地球人......
  • 关于 Spring Security 携带 token 反而 403 的问题
    https://www.cnblogs.com/liouzeshuen/p/16198795.html 某个目录下允许不登录访问.antMatchers("/activity/index").anonymous()但是传了token反而报403改成.antMatc......
  • 大家都能看得懂的源码 - 那些关于DOM的常见Hook封装(二)
    本文是深入浅出ahooks源码系列文章的第十五篇,该系列已整理成文档-地址。觉得还不错,给个star支持一下哈,Thanks。本篇接着针对关于DOM的各个Hook封装进行解读。use......
  • Firefox Firebug & Firefox DevTools All In One
    FirefoxFirebug&FirefoxDevToolsAllInOneFirebughttps://getfirebug.com/FirebugLiteforGoogleChromehttps://chrome.google.com/webstore/detail/fire......
  • 测试之前项目中关于useEffect的疑惑
    1.监听组件自己的数据第一种:组件内数据不发生改变,react自带的diffling算法,起了作用,页面不刷新,回调也不会执行importReact,{useEffect,useState}from'react'exp......
  • 关于vue.js:vue使用sass中deep报错
    转自:https://lequ7.com/guan-yu-vuejsvue-shi-yong-sass-zhong-deep-bao-cuo.html之前装了一个vue3.0的环境,结果搬砖的时候发现vue2.0的项目跑不了了然后照着网上说......
  • 好多不懂的和bug
    1、知道了MD5,2、知道了validate是干什么的,(validate中的rules中编写验证规则,规范输入),可以在管理员在网站修改数据的时候对输入进行限制。1<scripttype="text/javascri......