-3

我在完整的参考书中读到了这一段

C 对数组没有边界检查。您可以覆盖数组的任一端并写入其他变量的数据,甚至写入程序的代码。作为程序员,您的工作是在需要的地方提供边界检查。例如,这段代码编译不会出错,但不正确,因为for循环会导致数组计数溢出。

#include <stdio.h>

int main(){


    int count[10], i;
    /* this causes count to be overrun */
    for(i=0; i<15; i++) count[i] = i;

    for(i=0; i<15; i++) printf("%d ",count[i]);

    return 0;

}

当我尝试它给我的代码时

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

然后屏幕上显示运行时错误。错误是

array.exe 已停止工作

我的问题是:该错误的类型是什么?这是否意味着我的 IDE 会检查数组的边界?

4

4 回答 4

3

在第一个循环到达的那一刻i=10,您进入了未定义行为的领域(因为您正在编写超过 end 的内容count)。从那时起,任何事情都可能发生。

于 2013-08-29T09:44:29.717 回答
3

C不检查数组索引,它只做简单的指针算术。也就是说,标准将操作定义array[i]array + i
根据该计算的结果内存地址,可能会发生许多事情:

  • 地址指向函数的局部变量的位置:您修改局部变量。例如:

    int main()
    {
        int array[10];
        int a = 0;
    
        array[11] = 22; 
    
        printf(a%i,a); /* Prints 22 */
    }
    

    请记住,这里的重点是缓冲区溢出具有未定义的行为。我的示例无法正常工作,因为编译器可以在编译期间自由地重新排序变量布局,用于内存对齐和优化目的。

  • 地址指向全局变量的位置(这是一个非常大的索引/跳转,但可能会发生):效果与局部变量情况相同。

  • 地址指向子程序存储返回地址的位置:许多架构将函数的返回地址存储在寄存器中,但如果架构将其存储在函数的堆栈帧中......哇。尝试调试它!!!:)

  • 地址超出了进程的内存空间:现代操作系统总是检查内存访问以防止这种情况发生,所以当这种情况发生时,操作系统会踢你并抛出异常。

最后请注意,事情仅适用于发布编译。在调试模式下,编译器会添加大量代码来检查此类事情以抛出(提供)可理解且易于调试的异常。

例如:在分配动态数组时,windows debug-heap 首先用一个标志填充将使用的内存空间,该标志表示内存空间已准备好使用,但它不包含任何数据:这就是 hexspeak 0xBADF00D。在此之后,malloc检索内存位置,在数组周围添加 hexspeaks 以提供边界检查。

有关完整说明,请参阅本文

于 2013-08-29T10:12:28.953 回答
1

您的 IDE 与它无关。操作系统杀死了你的程序,因为它试图访问不属于它的内存。

这种类型的错误通常称为访问冲突。

于 2013-08-29T14:22:20.423 回答
0

没关系 - 你读过的文章的重点......

您应该做的是限制 for 循环,使其仅从 0 运行到 9。

或者,如果您真的需要 15 个项目,请展开数组以获取它们...

于 2013-08-29T09:44:05.123 回答