一道2016年nice的校招笔试题引发的思考

一道2016年nice的校招笔试题引发的思考,第1张

一道2016年nice的校招笔试题引发的思考

目录

声明

原题

题目详细解析

运行结果:

题目解析:

结论1:

注意点1:

注意点2:

 结论2:

 注意点3:

注意点4:

注意点5:


声明

今天的题,并非是完全出自于nice的笔试原题,今天的这道题出自于《C陷阱和缺陷》,只是两道题有异曲同工之妙!

原题
#include 
int main()
{
    int i = 0;
    int arr[10] = { 0 };
    for (i = 0; i <= 12; i++)
    {
        arr[i] = 0;
        printf("hehen");
    }
    return 0;
}

问题:这段代码在vs2019上会出现什么现象?这种现象是由什么原因造成的?我们应该如何避免像这样的问题?

题目详细解析
运行结果:

出现了死循环,即在屏幕上不停的打印"hehe"。

题目解析:

(1)i和arr是局部变量,放在栈区上

(2)栈区上的使用习惯:先使用高地址处的空间,再使用低地址处的空间

(3)数组随着下标的增长,地址是由低到高变化的

由这三点可以画出这段程序的内存图来,当然,这还要区分具体的编译器!

结论1:

arr[12]与变量i占用的是同一块空间,即地址值一样 

如果arr和i之间的空间合适的话,就有可能使用的arr数组向后越界访问到了i,造成循环变量i的改变,最终死循环。

注意点1:

这个代码是严格依赖环境的,例如vc 6.0 中i和arr是连续的,在gcc编译器中,i和arr之间有一个空间。

注意点2:

虽然此程序越界访问了,但是由于程序进入了死循环,所以不会报错,但是一旦把i<=12改成了i<=11,程序就会在i=11的地方会停止下来,此时已经构成了越界访问,程序自然会报错。如下图所示:

 结论2:

死循环会掩盖程序中的某些错误,比如数组越界访问。

 注意点3:

当把int i = 0;与int arr[10] = {0};交换之后,程序将不会出现死循环,但是程序的越界访问报错是少不了的。

注意点4:

此时也应该注意一下debug与release版本的区别:

很明显,在debug版本下,i的地址值比arr[9]的要大,而在release版本下,i的地址要比arr[9]的地址值要小,在release版本下进行了某些优化,即杜绝了我们上述出现的死循环的情况,在这种情况下,即使数组越界,也不会影响到i的值。

注意点5:

这种优化是无差别的,即无论你的代码是否越界,都会进行这样的优化。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5592958.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存