索引超过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
。 如果你对这个问题感到好奇,你一定要看看它。