本机 C 数组不进行边界检查。这将需要额外的指令和数据结构。C 是为效率和精简而设计的,因此它没有指定以性能换取安全的特性。
您可以使用像 valgrind 这样的工具,它在一种模拟器中运行您的程序,并尝试通过跟踪哪些字节已初始化和哪些未初始化来检测缓冲区溢出等事情。但这并不是绝对可靠的,例如,如果溢出访问恰好执行对另一个变量的合法访问。
在引擎盖下,数组索引只是指针算术。当您说 时arr[ 150 ]
,您只是将sizeof
一个元素添加 150 倍并将其添加到的地址arr
以获得特定对象的地址。该地址只是一个数字,它可能是无意义的、无效的,或者本身就是算术溢出。其中一些情况会导致硬件产生崩溃,当它找不到内存来访问或检测到类似病毒的活动时,但没有一个会导致软件生成的异常,因为没有软件挂钩的空间。如果你想要一个安全的数组,你需要围绕加法原理构建函数。
顺便说一句,您示例中的数组在技术上甚至不是固定大小的。
int len = 10; /* variable of type int */
char arr[len]; /* variable-length array */
使用非const
对象设置数组大小是自 C99 以来的一项新功能。您也len
可以是函数参数、用户输入等。这对于编译时分析会更好:
const int len = 10; /* constant of type int */
char arr[len]; /* constant-length array */
为了完整起见:C 标准没有指定边界检查,但也没有被禁止。它属于未定义行为的类别,或不需要生成错误消息的错误,并且可以产生任何影响。可以实现安全数组,存在该特征的各种近似值。C确实朝这个方向点头,使其非法,例如,获取两个数组之间的差异,以便找到正确的越界索引来访问数组B中的任意对象A。但是该语言非常自由-形式,并且如果 A 和 B 是同一内存块的一部分,则malloc
它是合法的。换句话说,您使用的 C 特定内存技巧越多,即使使用面向 C 的工具,自动验证就越困难。