大家好,nice公司面试的时候曾经出过一道题,难倒了很多人,今天和大家深度剖析一下。
#include
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("hehen");
}
我们运行一下,可以看出来它是一个死循环
原题就是这道,它问的是这道题为什么会存在死循环的一种情况。今天呢我就和大家好好地分析一下这道题。
在debug x86的环境底下,我对其进行了调试,大家看一下
我们可以看到当越界访问到arr[12]时,arr[12被赋值为0后,i的值由12变为了0,然后i=0,再进入循环,发现当arr[12]再次被赋值为0后,i也改为了0,然后不断循环下去。
那么为什么会出现这种情况呢?我们不妨想到arr[12]的地址和i的地址是不相同呢?因为只有这样,它们才会指向同一个空间,改变arr[i],不就是相当于改变了i吗?我们不妨打印一下:
经过打印我们看到arr[12]和i的地址确实相同,那么它们的地址为什么相同呢?
我们知道 i 和arr[i]都是局部数据,这些数据都是放在栈区里的而且是为数据开辟区间时先在高地址开辟,我们画图来看一下,
| 1 i的空间 高地址 |
| 2 |
| 3 |
| 4 4-14都为 arr的空间 arr[10] |
| 5. arr[9]
|
| 6. arr[8] |
| 7. ............. |
| 8. |
| 9. |
| 10. |
| 11. |
| 12. |
| 13. |
| 14. arr[0] 低地址 |
我们可以看到当i>10时,就算是越界访问了,arr在内存中存放是由地地址到高地址的,当向高地址去开辟空间是,那也就覆盖到i,使得i和arr地址一样,这时让arr[12]赋值为0,I也被赋值成了0,从而出现死循环的现象。
然而在release版本x86环境下,
我们可以发现没有陷入死循环,那这又是什么原因呢?我们在打印一下它们的地址看一下。
我们看到arr的址要比i 的地址高,那么当arr的地址即使越界访问也不会覆盖达到i,自然也不会出现死循环的现象了。 我们看到在debug和release两种版本下i的地址和arr地址相比较下的高低是不一样的, 这是因为release版本对代码做了优化,使得内存空间的存储方式发生了变化。
这就是我今天给大家分享的Nice公司一道题的深度剖析,如果有什么建议,欢迎大家提出来,如果觉得分析的不错的话,大家也可以给我点个赞,关注一下我。



