索引超过C数组的末尾

我在C中编写了一个简短的程序,只是为了看看当你索引数组末尾时会发生什么。

我发现它主要产生随机值(我知道它们实际上并不是随机的)直到一个点(在这种情况下52个索引超过结束),它每次产生0。 超过这一点的每个值和程序崩溃。 为什么是这样? 是程序结束分配内存空间?

main() { int ar[4]; ar[0] = 99; ar[1] = 45; printf("array: %d, %d random value: %d", ar[0], ar[1], ar[55]); } 

编辑:我还发现,如果我改变这个值总是最终为0(即ar [55] = 1000),那么程序的返回码就会增加。

…只是为了看看索引超过数组末尾时会发生什么

尝试访问超出范围的内存,调用未定义的行为 。 什么都可能发生,什么都可以。

在您的情况下,由于某种原因,可以从进程访问索引52的内存地址,因此它允许访问。 索引超过52个点到未分配给您的进程地址空间的内存区域,从而引发访问冲突导致段错误。 这根本不是确定性行为,并且您无法依赖调用UB的程序的输出。

访问数组边界之外的数组元素(在0之前或从其大小开始)是未定义的行为。 它可能产生或不产生值,它可能导致程序突然结束,它可能导致您的系统停止,重新启动或着火……

现代系统试图通过内存保护,用户空间限制等将未定义的行为限制在合理的限制范围内,但即使是用户空间代码错误也会产生可怕的后果:

  • 起搏器弄乱其定时值会导致过早死亡;
  • 银行软件溢出arrays边界可以覆盖账户余额信息,记入一些随机账户,数额巨大。
  • 你的自驾车可能比酒驾司机更糟糕……
  • 想想核电站控制软件,飞机仪表,军事……

毫无疑问,应该避免未定义的行为

关于退出状态,您的程序使用过时的语法来定义main() ,隐式返回类型,在C99及更高版本中不再支持,但不返回任何内容,这意味着它的返回值可以是任意随机值,每次执行都包含不同的值。 C99为main()函数指定了一个kludge并强制隐式return 0;main()的末尾,但依靠它是糟糕的风格。

类似地,在没有适当原型的情况下调用printf()是未定义的行为。 你应该在函数main()的定义之前包含

最后, ar[0]ar[1]main()中初始化,但ar[2]ar[3]不是。 请注意,访问未初始化的值也具有未定义的行为。 值可以是任何 ,您描述为随机值 ,但在某些系统上,它们可能是陷阱值,只需读取它们就会导致未定义的行为。

一些非常方便的工具可用于在简单和复杂的程序中跟踪此类问题,最值得注意的是valgrind 。 如果你对这个问题感到好奇,你一定要看看它。