偷网站源码直接建站,南通个人网站建设,ii6创建网站,模板网站优化文章目录1. 什么是bug#xff1f;2. 调试是什么#xff1f;有多重要#xff1f;2.1 调试是什么#xff1f;2.2 调试的基本步骤2.3 Debug和Release的介绍3.学会使用快捷键4.调试的时候查看程序当前信息4.1 查看临时变量的值4.2 查看内存信息4.3 查看调用堆栈4.4 查看汇编信息…
文章目录1. 什么是bug2. 调试是什么有多重要2.1 调试是什么2.2 调试的基本步骤2.3 Debug和Release的介绍3.学会使用快捷键4.调试的时候查看程序当前信息4.1 查看临时变量的值4.2 查看内存信息4.3 查看调用堆栈4.4 查看汇编信息4.5 查看寄存器信息5. 一些调试的实例5.1 实例一5.2 实例二5.3 大代码如何调试6. 如何写出好易于调试的代码6.1 优秀的代码6.2 示范6.3 const的作用7. 编程常见的错误1. 什么是bug bug是计算机领域专业术语原意是臭虫。现在用来指代计算机上存在的漏洞。 2. 调试是什么有多重要 所有发生的事情都一定有迹可循如果问心无愧就不需要掩盖也就没有迹象了如果问心有愧就必然需要掩盖那就一定会有迹象迹象越多就越容易顺藤而上这就是推理的途径。 顺着这条途径顺流而下就是犯罪逆流而上就是真相。 一名优秀的程序员是一名出色的侦探。
2.1 调试是什么 调试英语Debugging / Debug又称除错是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。 2.2 调试的基本步骤
发现程序错误的存在以隔离、消除等方式对错误进行定位确定错误产生的原因提出纠正错误的解决办法对程序错误予以改正重新测试
2.3 Debug和Release的介绍 Debug 通常称为调试版本 它包含调试信息并且不作任何优化便于程序员调试程序。 Release称为发布版本 它往往是进行了各种优化使得程序在代码大小和运行速度上都是最优的以便用户很好地使用。 代码
#include stdio.h
int main()
{char* p hello bit.;printf(%s\n, p);return 0;
}上述代码在Debug环境的结果展示 上述代码在Release环境的结果展示 在环境中选择 debug 选项才能使代码正常调试。
3.学会使用快捷键 最常使用的几个快捷键 F5 启动调试经常用来直接跳到下一个断点处。 F9 创建断点和取消断点 断点的重要作用可以在程序的任意位置设置断点。 这样就可以使得程序在想要的位置随意停止执行继而一步步执行下去。 F10 逐过程通常用来处理一个过程一个过程可以是一次函数调用或者是一条语句。 F11 逐语句就是每次都执行一条语句但是这个快捷键可以使我们的执行逻辑进入函数内部这是最长用的。 CTRL F5 开始执行不调试如果你想让程序直接运行起来而不调试就可以直接使用 Fn 辅助功能键 如果一个代码循环一千多次而我们认为他的错误在四百次的地方时要怎么调试 这时我们就可以给他加一个触发断点的条件或者使用一个if语句来进行判断。如下图所示
4.调试的时候查看程序当前信息
通过调试下的窗口键来进行查看
4.1 查看临时变量的值
在调试开始之后用于观察变量的值。
4.2 查看内存信息
在调试开始之后用于观察内存信息。 显示内存结果
4.3 查看调用堆栈 栈 只能从顶上放入再从顶上删除 通过调用堆栈可以清晰的反应函数的调用关系以及当前调用所处的位置。
4.4 查看汇编信息 可以切换到汇编代码。
4.5 查看寄存器信息 可以查看当前运行环境的寄存器的使用信息。
5. 一些调试的实例
5.1 实例一
实现代码求 123 … n! 不考虑溢出。
#include stdio.h
int main()
{int i 0;int sum 0;//保存最终结果int n 0;int ret 1;//保存n的阶乘scanf(%d, n);for (i 1; i n; i){int j 0;for (j 1; j i; j){ret * j;}sum ret;}printf(%d\n, sum);return 0;
}这时候我们如果3期待输出9但实际输出的是15 这时候我们就得通过调试找我们问题。 通过调试我们发现问题出现在ret的值上ret的值为每次结果值的累积效果所以在循环内部令ret1结果就为我们想要的结果。 代码修改后
#include stdio.h
int main()
{int i 0;int sum 0;//保存最终结果int n 0;int ret 1;//保存n的阶乘scanf(%d, n);for (i 1; i n; i){ret 1;int j 0;for (j 1; j i; j){ret * j;}sum ret;}printf(%d\n, sum);return 0;
}运行结果
5.2 实例二
#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;
}数组越界访问我们发现程序并不会崩溃而是陷入死循环这是为什么呢 通过调试我们发现arr[12]与i的地址一样改变arr[12]就改变了i arr与i之间到底空几个空间取决于编译器的内存分配 vc6.0 中间没有空间 gcc 中间空一个整形 vs 中间空两个整形 注 这个代码的运行结果是和环境相关的
5.3 大代码如何调试 例如我们写过的三子棋当出现问题时我们可以在感觉有问题的模块放上断点来进行调试。
6. 如何写出好易于调试的代码
6.1 优秀的代码 代码运行正常bug很少效率高可读性高可维护性高注释清晰文档齐全 常见的coding技巧 使用assert尽量使用const养成良好的编码风格添加必要的注释避免编码的陷阱 6.2 示范 模拟实现库函数strcpy strcpy string copy —— 字符串拷贝 代码演示
#include stdio.h
#include assert.h
//strcpy函数返回的是目标空间的起始地址char* my_strcpy(char* dest, const char* src)
{//断言 - 保证指针的有效性assert(dest src);char* ret dest;//把src指向的字符串拷贝到dest指向是的数组空间包括\0字符while (*dest *src){;}return ret;
}int main()
{char arr1[] hello world;char arr2[20] { 0 };//链式访问printf(%s\n, my_strcpy(arr2, arr1));return 0;
}6.3 const的作用
代码演示
#include stdio.h
//代码1
void test1()
{int n 10;int m 20;int* p n;*p 20;//ok?p m; //ok?printf(%d\n, m);
}
void test2()
{//代码2int n 10;int m 20;const int* p n;p m; //ok//*p 20;//noprintf(%d\n, m);
}
void test3()
{int n 10;int m 20;int* const p n;*p 20; //ok//p m; //noprintf(%d\n, m);
}
int main()
{//测试无cosnt的test1();//测试const放在*的左边test2();//测试const放在*的右边test3();return 0;
}结论 const修饰指针变量的时候 const 放在*的左边, *p不能改了也就是p指向的内容不能通过p来改变了。但是p是可以改变的p可以指向其他的变量const 放在的右边,限制的是pp不能改变但是p指向的内容p是可以通过p来改变的 练习 模拟实现一个strlen函数 参考代码 #include stdio.h
#include assert.h
int my_strlen(const char* str)
{int count 0;assert(str ! NULL);while (*str)//判断字符串是否结束{count;str;}return count;
}
int main()
{const char* p abc;//测试int len my_strlen(p);//strlen函数求\0之前字符串的长度printf(len %d\n, len);return 0;
}7. 编程常见的错误
1.编译型错误 接看错误提示信息双击解决问题。或者凭借经验就可以搞定。相对来说简单。 例如语句后的分号
2. 链接型错误 看错误提示信息主要在代码中找到错误信息中的标识符然后定位问题所在。一般是标识符名不 存在或者拼写错误。 例如
3.运行时错误 借助调试逐步定位问题。最难搞。 关于调试技巧的讲解七七就分享到这了有什么问题或者需要改进的地方欢迎评论区留言或者私信都可以哦