前言

软件调试,是开发过程中必备的技能。通过调试可以发现软件存在的bug,即缺陷。调试可以帮助开发者窥探到软件运行过程中的详细状态,从而为消除bug提供重要信息。调试的英文是debug,前面的de在英文中表示“反对”,“消除”。本文将会介绍日常开发中常用的、也是一名合格的Qt开发人员需要掌握的Qt软件基本调试方法,并结合不同场景加以说明,帮助读者查漏补缺,打牢基本功。

常用调试方法

1. 基本调试方法

1.1 以调试启动

以调试启动,是指软件在启动的同时,调试也随即开始。
在Qt项目中,点击Qt Creator左下角调试按钮,如下所示,即可以调试启动:

在VS中调试启动按钮为:

以调试启动是最常用的调试方法,因为它可以对软件启动到退出的全过程进行调试,所以是调试的首选方法,适用于绝大多数场景。

1.2 附加到进程

附加到进程是另外一种比较常用的调试方法,它是指在软件无调试启动一段时间后,再将调试器挂载到应用程序中进行调试。这种方法通常在以下场景使用:

  • 场景1:
    如果软件启动速度较慢(启动慢的原因很多,比如加载资源、加载插件等等)。调试本身就会使软件变慢,以调试启动,会导致软件启动速度更慢。而采用附加到进程的调试方法,可以在软件启动后,再调试软件,节省时间。但是如果你需要调试的代码段只在软件启动时刻执行一次,那就无法用此种方法,只能使用以调试启动的方法来调试。
  • 场景2:
    在软件是由windows批处理启动时,一般需要使用附加到进程的方法调试。
    通常使用批处理启动软件,是为了配置软件的启动环境,或进行一些启动前的预处理步骤。因为在开发环境中,启动软件仅仅能够配置命令行参数而已,无法进行复杂的环境配置,所以就无法直接以调试启动的方法调试。可能有的同学说,直接调试批处理文件是否可行,答案是不行,感兴趣的同学可以自己尝试。那么这样一来就只有使用附加到进程的方法调试了。

附加到进程,在Qt Creator中,选择菜单“调试”->“开始调试”->“关联到运行中的程序”,随后在弹出的进程列表中选择需要调试的进程即可,如下图所示:

在VS中,在菜单中选择“调试”->“附加到进程”,在弹出的进程列表中选择需要调试的进程即可,如下图所示:

1.3 启动后再调试

启动后再调试严格来说也是附加到进程。在Qt中,当软件启动后,可以点击下图所示的按钮,直接附加到进程调试:

这里就不再赘述。

2. 远程调试

远程调试用于通过网络对另外一台电脑上运行的软件进行调试。
通常用于以下场景:

  • 场景1
    假设目标电脑为实际运行环境。且不能安装开发环境,可能的原因有:目标电脑版本较老、性能较差、不具备安装开发环境的条件,抑或是时间紧急,没有时间安装配置开发环境。
    但是目标电脑可以接入网络,包括局域网和广域网。这种情况下可以在目标电脑上启动调试服务器;在自己的开发电脑上,在VS中使用源码实现远程调试。

调试服务器,又叫远程调试器,Remote Debugger,本地 VS 安装目录下的找到msvsmon.exe,拷贝到目标电脑上运行。

随后在目标电脑上配置调试服务器,包括监听端口、防火墙等。
在调试电脑上的VS 工程中,打开项目属性,点击调试选项卡,切换到远程 Windows 调试器进行配置。具体的配置过程,限于篇幅这里不再赘述,大家可自行搜索。

需要强调的是,发布的debug版本的软件一定要包含.pdb文件,即调试信息文件,它包含了符号的位置信息,用于定位源码,无pdb文件将无法调试。

3. windbg调试

windbg调试是指使用windbg调试软件在目标电脑上进行调试,这种调试方法的优点是不需要安装开发环境,不需要连接网络。只需要将目标电脑上运行的软件对应的源码,以及和目标电脑对应位数、版本的windbg软件拷贝到目标电脑上即可。

windbg调试时,需要进行源码目录配置等操作。windbg支持单步执行,执行到指定位置、查看变量、附加到进程等诸多功能,基本包含Qt/VS中的调试功能,甚至更加强大。当然,使用windbg调试需要一定的学习成本,因为其只在特定的场景下使用,一般只需要在用的时候根据网络上的教程现学即可。

和上面一样,被调试的软件必须含有.pdb文件,否则无法调试。

4. 仅日志调试

上面说的调试方法,都是使用调试器进行调试,可以看到软件运行时的详细信息。但是上述方法的缺点是必须需要和运行的目标软件建立某种连接。而日志调试不需要建立实质性的连接,日志仅仅为软件运行过程中调试信息的记录文本。日志调试需要先打印出重要的运行信息,在排查软件问题时,通过分析日志记录,推断出软件出现问题的原因。日志调试是一种在软件开发后期最省时省力、成本最低的调试方法。但是实现日志调试是一种从编写软件的第一行代码开始就进行的长期、持续的工作。编写代码时,在重要的位置上打印出重要的信息,是实现日志调试的必要工作。

Qt中提供了日志输出机制。如qDebug()、qInfo()、qCritical()、qFatal(),用于向控制台打印信息,当然也可以重定向输出到文件,后面的文章会加以说明。除此之外还有断言Q_ASSERT,可以在调试版本的软件运行时,在关键位置进行条件校验,校验失败时,弹出对话框提示并指明错误代码位置。

日志调试在软件中是必不可少的存在,任何一个良好的软件都会有日志记录。从另一个角度看,在编码过程中,我们要培养打印日志的好习惯,这也是提高编码水平的重要内容。

调试场景

1. 开发阶段调试

因为开发阶段一般环境准备比较充分,大部分时间使用调试器进行调试,包含上面提到的基本调试方法、远程调试方法、windbg调试方法。使用调试器调试可以直接看到内存变量、程序执行位置、对执行进行控制,可以快速定位问题。

软件调试不是目的,软件在设计和编码阶段要充分考虑各种输入输出情况,对异常的处理分支不能不管不问,不可图懒省事,要对软件质量负责,这是开发者的本职工作,是减少软件缺陷的关键。我们不仅要学习调试技术,还要建立起对软件正确的态度,成为一名合格的工程师。

2. 部署、维护阶段调试

部署维护阶段,因为部署维护时的软件运行环境会发生巨大变化,可能因为种种原因,调试会出现困难。这要求我们掌握并灵活运用多种调试手段,根据实际情况选择合适的调试方法,或者综合运用各种调试方法。在不具备调试条件时,通过协商、沟通创建必要的调试环境,最后解决软件问题,防止因软件问题产生损失,这会给我们带来很大的成就感。

结语

本文对笔者在工作中关于软件调试的一些经验方法进行了系统的总结,希望对想要做出优秀软件的同学有所帮助。

大家如有任何疑问,欢迎评论交流。

本文由微信公众号“Qt未来工程师”原创发布。

【精华】掌握Qt调试技术相关推荐

  1. 【Qt调试技巧】Profile配置使用及一些坑

    介绍 不知从哪个版本起,Qt Creator中的构建配置中,增加了一种新型配置,名叫"Profile",如下图所示: 官方对Profile的描述是:Profile是介于Debug和 ...

  2. 客户端dmesg_打印调试技术 printk klogd dmesg(解决打印信息的问题)

    4.2.1. printk #include printk(KERN_CRIT"error %s,%i",__FILE__,__LINE__); 注: 1). printk 函数中 ...

  3. shell脚本调试技术

    Shell脚本调试技术 曹 羽中 (caoyuz@cn.ibm.com), 软件工程师, IBM中国开发中心 曹羽中,在北京航空航天大学获得计算机软件与理论专业的硕士学位,具有数年的 unix 环境下 ...

  4. PHP程序员的优化调试技术和技巧

    使用调试器,可以设置断点并查看 PHP 代码到所设断点之前的浏览器输出.然后可以继续代码的执行并查看到下一断点之前的浏览器输出,然后再到下一个,直到 PHP 脚本完成. 现在把 "设置&qu ...

  5. [转载]Android开发常用调试技术记录

    ANDROID 调试技术: 1)Ps 指令 ls –l /proc/27/ cat /proc/27/cmdline       #cmdline文件表示了这个进程所在的命令行. cat /proc/ ...

  6. Linux调试技术介绍

    对于任何编写内核代码的人来说,最吸引他们注意的问题之一就是如何完成调试.由于内核是一个不与某个进程相关的功能集,其代码不能很轻松地放在调试器中执行,而且也不能跟踪. 本章介绍你可以用来监视内核代码和跟 ...

  7. linux内核调试技术 kprobe使用与实现

    Linux kprobes调试技术是内核开发者们专门为了便于跟踪内核函数执行状态所设计的一种轻量级内核调试技术.利用kprobes技术,内核开发人员可以在内核的绝大多数指定函数中动态的插入探测点来收集 ...

  8. Shell脚本的调试技术

    编程中必不可少的一点就是调试,Shell脚本以其强大的功能令人向往,当然,它的强大之处不只是体现在语言的实现功能上,更强大的是它的调试功能,下面,我将以实例讲解Shell脚本的调试技术. 下面是我所用 ...

  9. the cdb terminated,Qt调试器问题

    the cdb terminated,Qt调试器问题 没有找到原因:只是把头文件,静态库,动态库都添加进来,后面就可以调试了, the cdb terminated,Qt调试器问the cdb ter ...

最新文章

  1. c++函数模板_高考数学解答题得分模板——三角函数与解三角形
  2. 大数据工作的正确打开姿势
  3. XShell与虚拟机连接的IP问题
  4. 机房速度和带宽测试的简单方法
  5. ROS中catkin_make编译输出的可执行文件在哪?
  6. OpenCV扫描图像,查找表和时间测量
  7. AI降成本利器!阿里云弹性加速计算实例来了,最高节省50%推理成本
  8. 小学奥数 7647 余数相同问题 python
  9. curd日志记录php,ThinkPHP学习之CURD操作(一)
  10. Android笔记 隐式意图demo
  11. 面板数据回归模型(固定效应、随机效应、混合回归、变系数)、面板数据AR、VAR模型
  12. dell电脑计算机专业,戴尔Dell专用英语_电脑基础知识_IT计算机_专业资料.doc
  13. 每个人都应该知道的Android Studio快捷方式
  14. 《我也能做CTO之程序员职业规划》之二:做CTO的苹果定律
  15. 程序员的思维修炼7——积累经验
  16. TortoiseGit-创建分支、合并分支
  17. 判断当前线程是否有管理者权限
  18. LinuxCNC Stepconf设置教程
  19. 极通EWEBS虚拟化平台牵手厦门大学
  20. 计算机桌面设置,电脑怎么设置动态桌面

热门文章

  1. day35-hibernate映射 03-Hibernate持久态对象自动更新数据库
  2. iOS 开发疑难杂症(01)
  3. mysql中char与varchar的区别分析
  4. cocos2d-x 旅程開始--(实现单击与长按)
  5. ubuntu下修改mysql编码,使能支持中文
  6. PHP 免费视频教程
  7. 安装包卸载时如何删除安装时写在系统环境变量中的内容
  8. python利用有道词典翻译_使用Python从有道词典网页获取单词翻译
  9. java语言中的标识符_Java语言基本语法(一)————关键字标识符(Java语言标识符命名规范Java语言的包名、类名、接口名、变量名、函数名、常量名命名规则 )...
  10. res.status === 200含义