索引超过C数组末尾
我用C编写了一个简短的程序,只是想看看当索引超过数组末尾时会发生什么 我发现它主要产生随机值(我知道它们实际上不是随机的),直到一个点(在本例中,52个索引超过末尾),在这个点上它每次产生0。每一个值超过这一点,程序就会崩溃。为什么会这样?程序分配的内存空间是否已结束索引超过C数组末尾,c,arrays,undefined-behavior,C,Arrays,Undefined Behavior,我用C编写了一个简短的程序,只是想看看当索引超过数组末尾时会发生什么 我发现它主要产生随机值(我知道它们实际上不是随机的),直到一个点(在本例中,52个索引超过末尾),在这个点上它每次产生0。每一个值超过这一点,程序就会崩溃。为什么会这样?程序分配的内存空间是否已结束 main() { int ar[4]; ar[0] = 99; ar[1] = 45; printf("array: %d, %d random value: %d", ar[0], ar[1]
main()
{
int ar[4];
ar[0] = 99;
ar[1] = 45;
printf("array: %d, %d random value: %d", ar[0], ar[1], ar[55]);
}
Edit:我还发现,如果我修改这个值,结果总是为0(即ar[55]=1000),那么程序的返回码就会上升
。。。只是想看看当索引超过数组末尾时会发生什么
尝试访问超出绑定的内存时,调用。任何事情都有可能发生,任何事情都有可能发生
在您的情况下,由于某种原因,可以从进程访问索引52之前的内存地址,因此它允许访问。将超过52个点的索引指向未分配给进程地址空间的内存区域,从而引发导致SEGFULT的访问冲突。这根本不是一种确定性行为,而且您无法依赖调用UB的程序的输出
。。。只是想看看当索引超过数组末尾时会发生什么
尝试访问超出绑定的内存时,调用。任何事情都有可能发生,任何事情都有可能发生
在您的情况下,由于某种原因,可以从进程访问索引52之前的内存地址,因此它允许访问。将超过52个点的索引指向未分配给进程地址空间的内存区域,从而引发导致SEGFULT的访问冲突。这根本不是一种确定性行为,您无法依赖调用UB的程序的输出。访问数组边界以外的数组元素(在
0
之前或从其大小开始)是未定义的行为。它可能产生值,也可能不产生值,它可能导致程序突然结束,它可能导致系统停止、重新启动或起火
现代系统试图通过内存保护、用户空间限制等将未定义的行为限制在合理的范围内,但即使是用户空间代码错误也可能造成可怕的后果:
- 起搏器干扰其计时值可导致过早死亡李>
- 溢出数组边界的银行软件可能会覆盖帐户余额信息,并将不计其数的美元存入某个随机帐户
- 你的自动驾驶汽车可能比酒后驾车的人表现更糟
- 想想核电站控制软件、飞机仪表、军事设备
main()
的定义使用了过时的语法,隐式返回类型在C99和更高版本中不再受支持,但不返回任何内容,这意味着其返回值可以是任意随机值,包括每次执行的不同值。C99为main()
函数指定了一个kludge,并强制隐式返回0
位于main()
的末尾,但依赖它是不好的风格
类似地,在没有适当原型的情况下调用printf()。在定义函数main()
之前,应该包含
最后,ar[0]
和ar[1]
在main()
中初始化,但是ar[2]
和ar[3]
没有初始化。请注意,访问未初始化的值也有未定义的行为。这些值可以是任何值,您将其描述为随机值,但在某些系统上,它们可能是陷阱值,仅通过读取它们就会导致未定义的行为
一些非常方便的工具可用于跟踪简单和复杂程序中的此类问题,最显著的是valgrind
。如果您对这个主题感兴趣,一定要看看。访问数组边界以外的数组元素(在0之前或从其大小开始)是未定义的行为。它可能产生值,也可能不产生值,它可能导致程序突然结束,它可能导致系统停止、重新启动或起火
现代系统试图通过内存保护、用户空间限制等将未定义的行为限制在合理的范围内,但即使是用户空间代码错误也可能造成可怕的后果:
- 起搏器干扰其计时值可导致过早死亡李>
- 溢出数组边界的银行软件可能会覆盖帐户余额信息,并将不计其数的美元存入某个随机帐户
- 你的自动驾驶汽车可能比酒后驾车的人表现更糟
- 想想核电站控制软件、飞机仪表、军事设备
毫无疑问,应该避免未定义的行为
关于退出状态,您的程序对main()
的定义使用了过时的语法,隐式返回类型在C99和更高版本中不再受支持,但不返回任何内容,这意味着其返回值可以是任意随机值,包括每次执行的不同值。C99为main()
函数指定了一个kludge,并强制隐式返回0
位于main()
的末尾,但依赖它是不好的风格
类似地,在没有适当原型的情况下调用printf()。在定义函数main()
之前,应该包含
最后,ar[0]
和ar[1]
在main()
中初始化,但是ar[2]
和ar[3]
没有初始化。请注意,访问未初始化的值也有未定义的行为。这些值可以是任何值,您将其描述为随机值,但在某些系统上,它们可能是陷阱值,仅通过读取它们就会导致未定义的行为
有些人是汉人