实用的调试技巧
所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有
愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。顺
着这条途径顺流而下就是犯罪,逆流而上,就是真相。
基本步骤:
1、发现错误的存在
2、以隔离、消除等方式对错误进行定位
3、确定错误产生的原因
4、剔除纠正错误的解决办法
5、对错误进行改正,重新测试
Debug称为调试版本,它包含调试信息,且不作任何优化,便于程序员调试程序(程序员调试的版本)
Release称为发布版本,它往往进行了各种优化,使程序在代码大小和运行速度上都是最优的,以便用户更好得使用(测试人员测试的版本)
快捷键:
逐过程调试 F10
逐语句调试 F11 更细
切换断电 F9
启动调试 F5
学习:https://blog.youkuaiyun.com/mrlisky/article/details/72622009
查看程序当前信息:
查看临时变量:窗口–自动窗口/局部变量/监视
查看内存
查看调用堆栈 main函数也是被其他函数调用的
查看汇编信息
查看寄存器信息
实例:
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = {0};
for(i=0; i<=12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
运行结果是什么?发生什么问题?为什么?
死循环 越界访问 arr[12]与i的地址相同(偶然情况)(与编译器有关) 实际上是一个变量
栈区的使用习惯是:先使用高地址空间,再使用低地址空间
而数组随着下标的增长,地址是由低到高变化的
所以如果越界合适,就会导致程序死循环(会改变i的值)
c/c++对数组的下标是不做检查的 《c陷阱和缺陷》
Release版本下 不会死循环
可以利用system("pause");让代码暂停,观察结果//打印了13个hehe
可见代码进行了优化
i的地址变得比arr[]的地址要小了
如何写出好(易于调试)的代码
优秀的代码:
1. 代码运行正常
2. bug很少
3. 效率高
4. 可读性高
5. 可维护性高
6. 注释清晰
7. 文档齐全
常见的coding技巧:
1. 使用assert 断言 能把可以预见的错误暴露出来
2. 尽量使用const 保护住不想被改变的变量
3. 养成良好的编码风格 《高质量c++编程》
4. 添加必要的注释
5. 避免编码的陷阱
常见的错误分类:
编译型错误
直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。
链接型错误
看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在 (无法解析的外部符号)
一般是标识符名不存在或者拼写错误。
运行时错误
借助调试,逐步定位问题(最难搞) 栈溢出是运行时错误的一种,因此C程序为将栈溢出单独列出,栈溢出包含在运行时错误中。