内存访问越界是指程序试图访问未被分配或不允许访问的内存区域。在C语言中,这种情况通常发生在以下几种情况:
-
数组越界:访问数组中未定义的索引。例如,如果定义了一个大小为10的数组,试图访问数组的第11个元素(索引为10)就是越界。
int arr[10]; arr[10] = 5; // 越界访问
此时的越界访问时编译阶段是没有问题的,但是在执行阶段便会出现如下错误
-
指针越界:指针指向的内存位置超出了分配的范围。例如,在动态分配内存后,试图通过指针访问已经释放的内存或超出分配的范围。
int *ptr = (int *)malloc(10 * sizeof(int)); ptr[10] = 5; // 越界访问
此时的越界访问时编译阶段是没有问题的,在执行阶段边也是能执行的(在没有打印访问越界值的情况下),如果我们要打印这个访问的越界值,那便会出现如下错误。
int *ptr = (int *)malloc(10 * sizeof(int)); ptr[10] = 5; printf("%d", ptr[10]);
有时你在访问free掉的指针数据时,也能编译和执行,主要是因为以下情况:
(1)未定义行为:一旦你调用free()
,系统会标记那块内存为可用,但并不意味着该内存中的数据会被立即清除。内存的内容可能仍然保持不变,直到该内存被重新分配。访问已释放的内存会导致未定义行为,程序的表现可能不同,这取决于操作系统、编译器和具体的运行环境。
(2)内存重用:在free(ptr);
后,分配给ptr
的内存块可以被其他分配请求使用。因此,如果在这之后有其他代码执行,可能会改变该内存的内容,但在你的程序中,访问它仍然可能会得到之前的值。
(3)优化和环境影响:编译器的优化可能影响程序的行为,导致某些值被缓存或保留,或者程序的运行环境可能在某些情况下表现出意外的结果。 -
栈溢出:在函数中分配了过多的局部变量,导致栈空间不足,可能覆盖其他变量或返回地址。
-
写入只读内存:尝试修改程序的只读部分(如字符串常量或代码段)。
内存访问越界会导致未定义行为,这可能表现为程序崩溃、数据损坏或安全漏洞。因此,在编写C程序时,必须仔细检查内存访问的合法性,确保不会越界。