C语言详解系列——关于调试那些事

一道笔试题

在之前的学习当中,我们总是提到调试,在我们想知道代码究竟怎么运行时,我们就需要用到调试,当我们的代码出现了bug,通过观察我们找不到哪里出现了问题,这时我们也需要使用到调试,例如下面这道笔试题,我们就出现了问题

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
   {
        arr[i] = 0;
        printf("hehe\n");
   }
   
    return 0; 
}

我们通过观察一看,数组元素有10个,但是遍历数组时,我们越界访问了,所以当i = 10的时候,数组越界访问,程序应该崩溃才对,但是真的是这样嘛?我们让代码跑起来
在这里插入图片描述
我们运行起来我们发现,代码并没有崩溃,而是死循环打印hehe了,这是为什么呢?这令我们百思不得其解,这时候调试的作用就体现出来了。

调试那些事

如何调试

调试的基本步骤如下

1.发现程序错误的存在
2.以隔离、消除等方式对错误进行定位
3。确定错误产生的原因
4.提出纠正错误的解决办法
5.对程序错误予以改正,重新测试

注意在我们的编译器中有两个版本

1.Debug 通常称为调试版本,它包含调试信息,并且不做任何优化,便于程序员调试程序
2.Release 称为发布版本,它往往时进行了个各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。

几个调试的快捷键

f5
启动调试,经常用来直接跳到下一个断点处。
f9
创建断电和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。
f10
逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者一条语句。
f11
逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最长用的)。
ctrl + f5
开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。

我们在调试的过程中还可以观察内存信息,查看临时变量的值,查看调用的堆栈,查看汇编信息,查看寄存器信息等。

在调式中寻找答案

好了,我们了解了调试的基本信息,下面让我们通过调试找到刚才笔试题中的问题。

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
   {
        arr[i] = 0;
        printf("hehe\n");
   }
   
    return 0; 
}

在这里插入图片描述
我们通过调试可以查看变量iarr[i]的地址,当我们再次执行程序,i = 12
在这里插入图片描述
我们可以通过调试看见,变量i的地址与arr[i]的地址相同,我们执行arr[i] = 0;时将i也赋值成0了,所以程序才会死循环执行。

在这里插入图片描述
这就是调试在我们写程序当中的作用。

原理讲解

好了我们知道是哪里出现了问题,那么为什么会出现这样的问题呢。原因是变量iarr[10]都是在栈区开辟内存空间的,而栈区空间的使用规则是,先使用高地址在使用低地址,数组元素访问时由低地址到高地址开始调用,所以当数组越界访问时,有机会访问到i的空间地址,将变量修改为0,所以会造成死循环。
在这里插入图片描述

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悲伤猪小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值