今天和大家分享一下我写代码所遇到的问题:越栈访问所造成的死循环。(这里我所用的是VS2022编译器)
首先,看一下代码:
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <= 15; i++)
{
arr[i] = 0;
printf("Hello World!\n");
}
return 0;
}
运行结果:
我们发现这个代码的运行结果是:死循环打印 “Hello World!”.
下面解释一下为什么会出现这种现象。
(一) 当我们在编译器中创建一个变量时,系统会给我们分配内存一块空间来保存这个变量。例如我们这里创建一个整型类型的变量a和b.
int a = 0;
int b = 0;
而在内存中,又分为栈区,堆区,和静态区。这里我们所创建的局部变量就被存放在栈区中。
通过调试窗口中的监视器,我们可以看到系统所给a,b分配空间的地址
从地址可以看出,我们创建的a,b 局部变量,a被放在了低地址处, b被放在了高地址处
可能你在这里会有疑惑,不是先创建的变量存放在高地址处,后创建的变量存放在低地址处吗?其实你的这个疑惑也是正确的,不是我所说的是正确的,而你所说的是错误的。
在64位机器上,先使用低地址再使用高地址;
在32位机器上,先使用高地址后使用低地址。
回到我们所写的代码来,我们先创建一个i 变量,又创建了一个有十个元素的整形数组,而数组元素的地址是随着下标的增大而增高。下面我们来看图解:
我们可以看到,i 的地址和 arr[15] 的地址相同,这也就意味着当我们越界访问到 arr[15] 时,我们把 arr[15] 赋值成0时,i 的值也被改变为 0,这样 i 的值会一直小于等于15,不会跳出循环。
这也就解释了,上述代码为什么会死循环打印 “Hello World!”了。
当然,在32位机器上也是同样的道理,只不过需要先创建数组arr, 在创建变量 i, 总的来说就是需要通过arr的越界访问到 i 的地址,能够改变 i 的值,就会出现这种现象。
———————————————————————————————————————————
今天的分享就到这里了,如果,你感觉这篇博客对你有帮助的话,就点个赞吧!感谢感谢……