C语言VirtualBox Ubuntu虚拟机下动态分配数组内容非预期变更问题
问题根因及修复方案
你遇到的是典型的堆内存缓冲区溢出导致的未定义行为,核心错误出现在动态内存分配行,具体原因如下:
- 内存分配时大小参数填写错误
你声明的array是my_obj*类型,用于存储多个my_obj结构体实例,但是calloc的第二个参数错误填写为sizeof(my_obj*)(即指针类型的大小,32位系统下为4字节、64位下为8字节),远小于my_obj结构体本身的实际大小,导致分配的堆内存空间远小于实际需要的容量。array2也存在完全相同的错误。
后续你在给数组元素赋值时,写入操作直接越界,踩踏了相邻的堆内存区域。第一次打印正常是因为刚写入的内容还没被覆盖,当你填充array2时,越界写入的操作会覆盖array对应内存区域的内容,就出现了无规律的随机值。 - 其他可能的触发原因
如果修复上述问题后现象依然存在,可排查以下两点:- 全局变量
arr_length/arr_length_2的实际值大于预期,导致循环赋值时超出分配的内存边界 my_obj/my_obj2结构体包含柔性数组成员,直接用sizeof(类型)计算的大小没有包含柔性数组需要的内存空间,同样会导致分配不足
- 全局变量
修复代码
将内存分配行改为以下写法即可,推荐第二种写法,避免后续修改类型时重复出现同类错误:
// 写法1:明确指定结构体类型 my_obj* array = calloc(arr_length, sizeof(my_obj)); my_obj2* array2 = calloc(arr_length_2, sizeof(my_obj2)); // 写法2:解引用指针自动获取目标类型大小,更安全 my_obj* array = calloc(arr_length, sizeof(*array)); my_obj2* array2 = calloc(arr_length_2, sizeof(*array2));
注:C语言本身不做内存边界检查,越界访问属于未定义行为,不会触发显式报错,只会出现值篡改、段错误等随机现象,和你使用的虚拟机、Ubuntu系统没有关联。
内容的提问来源于stack exchange,提问作者warty
相关产品推荐
相关产品推荐

