我最近开始学习C语言,我正在上一门以C为主题的课程。我目前正在玩循环,我遇到了一些奇怪的行为,我不知道如何解释。

#include <stdio.h>

int main()
{
  int array[10],i;

  for (i = 0; i <=10 ; i++)
  {
    array[i]=0; /*code should never terminate*/
    printf("test \n");

  }
  printf("%d \n", sizeof(array)/sizeof(int));
  return 0;
}

在我运行Ubuntu 14.04的笔记本电脑上,这段代码没有崩溃。它运行到完成。在我学校运行CentOS 6.6的电脑上,它也运行得很好。在Windows 8.1上,循环永远不会终止。

更奇怪的是,当我将for循环的条件编辑为:I <= 11时,代码只在运行Ubuntu的笔记本电脑上终止。它永远不会在CentOS和Windows中终止。

有人能解释一下内存中发生了什么吗?为什么运行相同代码的不同操作系统会产生不同的结果?

编辑:我知道for循环越界了。我是故意这么做的。我只是不明白在不同的操作系统和计算机上,这种行为是如何不同的。


当前回答

漏洞存在于以下代码段之间:

int array[10],i;

for (i = 0; i <=10 ; i++)

array[i]=0;

由于数组只有10个元素,在最后一次迭代中数组[10]= 0;是缓冲区溢出。缓冲区溢出是未定义的行为,这意味着它们可能格式化您的硬盘驱动器或导致恶魔从您的鼻子里飞出来。

所有的堆栈变量都是相邻排列的,这是很常见的。如果i位于数组[10]写入的位置,则UB将i重置为0,从而导致未终止循环。

要修复,将循环条件更改为i < 10。

其他回答

你声明int array[10]表示数组的索引为0到9(它总共可以容纳10个整数元素)。但是接下来的循环,

for (i = 0; i <=10 ; i++)

将循环0到10意味着11次。因此,当i = 10时,它将溢出缓冲区并导致未定义行为。

所以试试这个:

for (i = 0; i < 10 ; i++)

or,

for (i = 0; i <= 9 ; i++)

错误是在部分数组[10]w/c也是I的地址(int数组[10],I;)。 当数组[10]被设置为0时,I将为0 w/c重置整个循环和 导致无限循环。 如果数组[10]在0-10之间,就会出现无限循环。正确的循环应该是(i = 0;I <10;我+ +){…} int数组[10],我; For (i = 0;I <=10;我+ +) array[我]= 0;

因为你创建了一个大小为10的数组,for循环条件应该如下所示:

int array[10],i;

for (i = 0; i <10 ; i++)
{

目前,您正在尝试使用数组[10]从内存中访问未分配的位置,这导致了未定义的行为。未定义行为意味着您的程序将以不确定的方式运行,因此它可以在每次执行时给出不同的输出。

漏洞存在于以下代码段之间:

int array[10],i;

for (i = 0; i <=10 ; i++)

array[i]=0;

由于数组只有10个元素,在最后一次迭代中数组[10]= 0;是缓冲区溢出。缓冲区溢出是未定义的行为,这意味着它们可能格式化您的硬盘驱动器或导致恶魔从您的鼻子里飞出来。

所有的堆栈变量都是相邻排列的,这是很常见的。如果i位于数组[10]写入的位置,则UB将i重置为0,从而导致未终止循环。

要修复,将循环条件更改为i < 10。

你有一个边界违反,在非终止平台上,我相信你无意中在循环结束时将I设置为0,这样它就会重新开始。

数组[10]无效;它包含10个元素,从数组[0]到数组[9],数组[10]是第11个。你的循环应该在10之前停止,如下所示:

for (i = 0; i < 10; i++)

数组[10]落在实现定义的位置,有趣的是,在两个平台上,它落在i上,这些平台显然是直接放在数组后面。I被设置为0,循环将永远继续下去。对于其他平台,i可能位于array之前,或者array可能在它之后有一些填充。