C语言动态数组缩容时realloc触发堆损坏invalid next size问题求助
堆损坏原因及排查方案
核心错误原因
- 数组下标越界直接破坏堆结构:你在delete函数中将待删除元素拷贝到末尾时,写了
deepcopy_pet(&log->array[log->cap], &temp, YES);。动态数组的下标范围是0 ~ cap-1,log->cap已经超出了数组的合法访问边界,越界写入直接破坏了malloc/realloc在堆上维护的块控制信息,这就是realloc(): invalid next size报错的直接诱因,也是valgrind报非法读写的根因。 - 元素移动逻辑完全错误:你计算移动范围时错误使用了
idtoDelete(待删除记录的业务ID)替代数组下标i,distance = log->size - idtoDelete、calibration = distance + idtoDelete这两行逻辑完全错误,会导致要么移动元素个数不对,要么直接访问非法内存。正确的移动范围应该是将下标i+1到log->size-1的所有元素向前挪1位,循环终止条件应该是j < log->size。 - realloc扩容大小计算错误:UPLIM分支的realloc计算大小时写了
sizeof(pet) * (log->size) + DEFAULTVIRGIN,这里计算单位不统一,加的DEFAULTVIRGIN是字节数而非pet结构体的个数,实际分配的内存远小于你预期的大小,会导致后续写入越界。正确写法应该是sizeof(pet) * (log->size + DEFAULTVIRGIN)。 - 临时对象内存泄漏:你调用
deepcopy_pet(&temp, &log->array[i], YES);给temp的成员变量申请了堆内存,但temp用完后没有主动free对应的内存,长期运行会导致内存泄漏。
修复建议
- 修正末尾写入的下标,将
log->cap改为log->size(你删除元素后已经执行了log->size--,此时log->size就是原来有效元素的最后一位的下一位,属于待删除元素存放的合法位置) - 删掉错误的distance、calibration计算逻辑,元素移动的循环改为:
for (j = i + 1; j < log->size; j++) { deepcopy_pet(&log->array[j - 1], &log->array[j], NO); }
- 修正UPLIM分支的realloc大小计算逻辑,统一用pet结构体个数乘以单结构体大小。
- 每次使用完temp变量后,手动free temp的sex、breed、pet_age成员,避免内存泄漏。
内容的提问来源于stack exchange,提问作者qiu
相关产品推荐
相关产品推荐

