调试
调试,又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。
调试的基本步骤
- 发现错误的存在
- 以隔离、消除等方式对错误进行定位
- 确定错误产生的原因
- 提出纠正错误的解决办法
- 对程序错误予以改正,重新测试
debug和release
Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序
Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
windows环境调试
- 调试环境的准备
在环境中选择debug选项,才能使代码正常调试 - 学会快捷键
F5:启动调试,经常用来直接调到下一个断点处
F9:创建断点和取消断点
断点:可以在程序的任意位置设置断点,这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去
F10:逐过程。通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。
F11:逐语句。每次执行一条语句,可以使我们的执行逻辑进入函数内部。(最常用)
Ctrl+F5:开始执行不调试,让程序直接运行起来。
- 调试的时候查看程序当前信息
查看临时变量的值、当前运行环境的寄存器的使用信息等 - 多尝试调试
实例
//求阶乘和,不考虑溢出
int main() {
int n = 0;
scanf("%d", &n);
int i = 0, j = 0;
int ret = 1;
int sum = 0;
for(j = 1; j <= n; j++) {
for (i = 1; i <= j; i++) {
ret *= i;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
语法没有错误,但运行结果与预期不符,调试就是解决运行错误!
打开监视窗口,发现ret的值不符合预期,修改代码:
int main() {
int n = 0;
scanf("%d", &n);
int i = 0, j = 0;
int ret;
int sum = 0;
for (j = 1; j <= n; j++) {
ret = 1;
for (i = 1; i <= j; i++) {
ret *= i;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
//实例2
int main() {
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <= 12; i++) {
arr[i] = 0;
printf("a");
}
return 0;
}
运行后出现死循环,打开监视窗口发现arr[10]、arr[11]、arr[12]的值都被改成0,而&i==&arr[12],所以此时i又被赋值为0,产生死循环。
i和arr是局部变量,放在栈区上,而栈区内存的使用习惯是:先使用高地址空间,再使用低地址空间,数组随着下标由低到高增长地址,由于先定义i,所以i为更高地址,在arr溢出后,很有可能访问到i;如果后定义i,那么会报错:非法访问内存。
//实例3
//输入一个整数数组,实现函数
//调整该数组中的数组的顺序
//使得数组中所有的奇数位于数组的前半部分,偶数位于后半部分
void move(int arr[], int sz) {
//从前往后找偶数,从后往前找奇数,然后交换
int left = 0;
int right = sz - 1;
while (left < right) {
while ((left < right) && (arr[left] % 2 == 1)) {
left++;
}
while ((left < right) && (arr[right] % 2 == 0)) {
right--;
}
if (left < right) {
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
}
void print(int arr[], int sz) {
int i = 0;
for (i = 0; i < sz; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
move(arr, sz);
print(arr, sz);
return 0;
}
如何写易于调试的代码
1.代码运行正常
2.bug很少
3.效率高
4.可读性高
5.可维护性高
6.注释清晰
7.文档齐全
常见coding技巧
1.使用assert
2.尽量使用const
3.养成良好的编码风格
4.添加必要的注释
5.避免编码的陷阱
编程常见错误
编译型错误:直接看错误提示解决问题
链接型错误:看错误提示,主要在代码中找到错误信息中的标识符,定位问题所在。一般是标识符名不存在或者拼写错误
运行时错误:借助调试逐步定位问题