1.何为bug?
计算机程序缺陷
第一个被发现的bug:飞蛾导致了计算机错误
2.调试及其重要性
2.1 调试(Debug/Debugging)
又称除错,指发现和减少电子设备中程序错误的过程。
2.2 调试步骤
- 发现问题
- 定位问题及错误
- 发现原因
- 提出解决方法
- 实施解决方案并测试
2.3 Debug与Release
Debug:调试版本的可执行程序(在Debug模式下进行调试)
Release:发布版本的可执行程序(往往是代码大小和运行速度最优的)
3. Windows环境调试
linux开发环境的调试工具为gdb
3.1 调试环境为Debug
3.2 常用快捷键
3.2.1 F5
启动调试(常与断点一起使用,可快速运行到断点处到达想要的地方)
3.2.2 F9
创建或取消断点(任意位置)
断点,让程序快速运行到断点处,用于调试
在循环中,同一断点可能会执行多次
3.2.3 F10
逐过程运行(一次函数调用/一个语句)
3.2.4 F11
逐语句运行(会进入调用函数内部)
3.2.5 CTRL+F5
直接执行,不调试
3.3 调试时查看程序当前信息
注意:开始调试后才能查看
3.3.1 查看临时变量
首选:开始调试->调试->窗口->监控->输入想要查看的变量
自动变量监视麻烦
3.3.2 查看内存信息
开始调试->调试->窗口->内存
3.3.3 查看调用堆栈
开始调试->调试->窗口->调用堆栈
3.3.4 产看汇编信息
- 右击鼠标->转到反汇编
- 开始调试->窗口->反汇编
3.3.4 查看寄存器信息
开始调试->窗口->寄存器
4. 初期阶段多调试,熟练掌握调试技巧,使用快捷键
5. 敲出好代码
5.1 优秀的代码
- 能够解决问题、需求
- bug少
- 效率高
- 可读性高
- 可维护性高
- 注释简洁明了
- 文档齐全
常用的coding技巧
- 使用assert
- 尽量使用const
- 养成良好的编码风格
- 添加必要的注释
- 避免编码陷阱
5.2 const
const修饰指针变量时
- 常量指针:const在*左边,修饰指针指向的内容,无法通过该指针修改指向的内容,但可通过其他指针修改指向的内容
- 指针常量:const在*右边,修饰指针变量本身,无法修改指针变量
6. 常见编程错误
6.1 编译型错误
- 双击错误提示,查看并修改
- 凭经验搞定
6.2 链接型错误(LNk)
- 无法解析的外部符号
- 查看错误信息提示,主要看标识符,定位问题所在(一般是标识符不存在或拼写错误)
6.3 运行时错误
- 借助调试,定位问题
7. 积累错误案例,熟记于心
例1——死循环(数组访问越界)
VS2019,Debug
#include <stdio.h>
int main(
{
int i= 0;
int arr[10] = {0};
for(i=0;i<=12;1++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
i和arr[12]是同一个地址
局部变量是放在内存中的栈区的
栈区的使用习惯是:
先使用高地址处的空间,再使用低地址处的空间
数组随着下标的增长,地址是由低到高变化
在VC6.0时,i和arr之间无多余的空间
在gcc时,i和arr之间有一个整型空间
例2——自定义strcpy(字符串拷贝)
空间小
char *my_strcpy(char *destination,char *source)
{
//判断是否为空指针
//if(destination == NULL || source == NUll)
//{
// return ;
//}
//断言 Debug中
//assert中可以放一个表达式,如果表达式的结果为假,则报错,为真,则无提示
//头文件<assert.h>
//assert(source != NULL)
//assert(destination != NULL)
assert(destination && source)
char *ret=destination;
while(*destination++ = *source++){}
return ret;
}
使用指针记得判断是否为空(assert),以及是否对指针或指针指向的内容进行改变(const)
使用搜索工具学习源码
8. 写程序的三种境界
- 看代码是代码
- 看代码不是代码,是内存
- 看代码还是代码