目录
1.什么是bug?
大白话:计算机程序上的错误,导致程序无法编译运行或者陷入死循环。
2.调试是什么?有多重要
所有发生的事情一点有迹可循,如果问心无愧,就不需要掩盖也就没有迹象,如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多越容易顺藤而上,这就是推理的途径。顺着这条途径顺流而下就是犯罪,逆流而上,就是真相
一名优秀的程序员是一名出色的侦探。
每一次调试都是尝试破案的过程
调试基本步骤
- 发现程序错误的存在
- 以隔离,消除等方式对错误进行定位
- 确定错误产生的原因
- 提出纠正错误的解决办法
- 对程序错误予以改正,重新测试
3.debug和release的介绍
debug 通常称为调试版本,他包含调试信息,并且不做任何优化,便于程序员调试程序
release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,一般用户更好的使用
4.VS2019环境常用调试方式
F5 启动调试,F9 设置断点(可以设置条件)搭配使用,F10逐过程,F11逐语句搭配使用
监视窗口,内存窗口,调用堆栈,局部变量,自动窗口,寄存器,反汇编,常使用这些窗口来监视程序运行的过程。
5.一些调试的实例
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
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("hehe\n");
}
return 0;
}
1.报错原因:i 和 arr是局部变量
局部变量是放在栈区上的
栈区内存的使用习惯是:先使用高地址空间,在使用低地址空间
2.数组随着下标的增长地址是由低到高变化的,在上面的程序中数组访问越界了,访问到了i使程序陷入死循环,
6.如何写出好的代码(易于调试的代码)
例如:实现函数my_strcpy(char *dest,,char *src)函数:拷贝字符串
注:为了写出好的代码我们需要考虑到任何可以想到的bug,
(1)可能出现的问题1:因为函数my_string需要引用俩个指针参数,如果指针为空指针我们进行解引用操作,编译则会报错,为了避免这种情况我们需要用到函数assert()函数进行断言操作
assert()函数:当我们不允许什么情况发生时,如果发生则报错
例:条件src不能等于空指针,如果为空则报错
(2)可能出现的问题2:避免程序员将拷贝数组和被拷贝数组弄反我们需要用到关键字const
const:修饰变量,这个变量是常变量不能修改,但本质上还是变量
例:当函数my_strcpy()函数中while循环,如果条件写为*src++=*dest++系统则会报错提醒,告知程序员,const关键字修饰的变量不能被修改,也就是说指针src所指向的数组是我们要拷贝的数组,不是要覆盖的数组。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
void my_strcpy(char*dest,const char*src)
{
assert(dest != NULL);//断言
assert(src!=NULL);//引用头文件#include <assert.h>
//assert()函数,当我们不允许什么情况发生时,如果发生则报错
//例:条件src不能等于空指针,如果为空则报错
while(*dest++=*src++)
//因为const修饰变量src,这个变量是常变量不能修改,所以只能在赋值语句的右边,
{
//复制字符串
}
}
int main()
{
char arr1[20] = "****************";
char arr2[] = "hellow";
my_strcpy(arr1, arr2);
printf("%s",arr1);
return 0;
}