实用调试技巧及一个出现过的笔试题目

今天课的内容是关于实用调试技巧

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;
}
这个代码运行的结果是  :  死循环,一直打印 hehe

首先,这个代码有明显的越界访问内存的错误,但是它并没有报错或者崩溃。

经过调试发现,当我的arr数组中每个元素都被替换成了0之后,i来到了10,进入for循环,紧接着它会把arr[10]也赋值为0,直到arr[12]时,arr[12]=0的同时,i也变成了0

 复习一个调试的技巧

当发现问题时,我需要来到arr[10]处,观察越界后程序的走向,

arr[i] = 0;        只需要在这行代码用F9添加一个断点,然后右键设置条件 i==10

按F5可以直接来到满足条件的断点处。

 

监视窗口发现,当来到arr[10],arr[11]时,它们未被初始化定义,也未被赋值为0的时候,他们都是随机值。

 

而arr[12]未被赋值时,它的值是12,与i相同。

赋值后,arr[12]变为0,同时 i 也变成了0,这就是死循环的原因所在,在本该跳出循环的时候,i=0,就又满足了进入for循环的条件,而当i++到12时,它又会重新变为0。

而通过地址发现,i和arr[12]的地址是相同的。

 

原理解释

arr 和 i 都是局部变量,局部变量是放在栈区

栈区的使用原则是,先使用高地址空间,再使用低地址空间

arr是数组,数组中元素的地址随着下标从低到高

代码中,i是先被定义的,被放在了高地址空间,arr被放在相对低地址空间,随着元素下标的上升,地址也会越来越高,越界访问后,就有可能访问到 i 所在的地址,将它赋值。这里到底会不会访问到i,什么时候访问到i,会受到编译环境的影响。我这里使用的是vs2019。

当 arr先被定义时,不会出现死循环,但是运行时程序会崩溃。因为在循环结束后,会发生越界访问报错。

而上述代码会因为进入死循环中而没有机会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值