一、调试
(一)调试步骤
- 发现程序错误的存在
- 以隔离消除等方法确定错误位置
- 确定错误产生原因
- 提出解决办法
- 对程序改正,重新测试
(二)Debug和Release
- Debug:包含调试信息,不做任何优化,便于程序员调试。
- Realse:往往进行了优化,程序在代码大小和运行速度上都最优。
在反汇编下,Debug和Release的代码量也是不一样的。
(三)快捷键
F5:直接来到下一个断点处(注意:循环处的断点难以一次跳出)。
F9:启用或创建断点(注意:右击可以启用条件断点)。
F10:逐过程,一个过程可以是一次函数调用或者是一条语句(颗粒度比较大)。
F11:逐语句,可以执行逻辑进入函数内部(颗粒度比较小)。
CTRL+F5:开始执行不调试。
其他快捷键
二、查看信息
需要在开始调试后才能查看。
(一)临时变量
调试->窗口->监视
注意,要查看函数内部的数组,需要在监视窗口输入数组名,行数。
(二)内存信息
调试->窗口->内存(输入地址就可以看到内存信息)
(三)调用堆栈
调试->窗口->堆栈(可以清晰反应函数调用关系和当前调用所处位置)
(四)查看汇编信息
右击->反汇编
(五)查看寄存器信息
调试->窗口->寄存器
三、代码习惯
- 使用assert
注意:使用assert要包含assert.h,assert()内内容为假就报错,可以用来检查空指针。 - 尽量使用const
const放在*左边,修饰的是指针指向的内容,指针可以改变,指向的内容不可以改变。
const放在*右边,修饰的是指针,指针不可以改变,指向的内容可以改变。 - 良好的编码风格
- 添加必要注释
- 避免编码陷阱
实现strlen():
size_t my_strlen (const char * str)
{
const char *eos = str;
while( *eos++ ) ;
return( eos - str - 1 );
}
实现strcpy():
char * my_strcpy(char * dst, const char * src)
{
char * cp = dst;
while( *cp++ = *src++ );
return( dst );
}
四、常见编程错误
- 编译性错误(.c):双击错误可以找到(语法错误)。
- 链接性错误(.obj):无法解析的外部错误,一般是标识符号命名不存在或者拼写错误(没有包含头文件等)。
- 运行时错误(.exe):需要逐步调试。