C语言双字符指针动态重分配报错:realloc(): invalid next size
嘿,我来帮你拆解下这个realloc(): invalid next size错误的根源,以及怎么修复它:
问题根源分析
你的代码里有两个致命的内存管理问题,直接导致了堆结构被破坏,最终触发了错误:
- 数组越界访问,破坏堆元数据:初始
buf = malloc(sizeof(char*))只分配了能容纳1个char*的空间,但循环从i=0跑到i=19。当i>=1时,buf[i]访问的是超出分配范围的内存——这会直接篡改堆的内部管理信息,虽然不会立刻崩溃,但后续的realloc会检测到堆损坏,抛出invalid next size错误。你看到第4次重分配时崩溃,只是因为堆损坏到一定程度才被触发而已。 - 未正确保存
realloc的返回值:realloc在无法原地扩容时,会分配一块新内存并把旧数据拷贝过去,同时释放旧内存。但你现在只是调用了realloc却没把返回值赋值给buf,这会导致两个问题:一是旧内存被释放后buf变成野指针,二是新分配的内存地址丢失,造成内存泄漏。
修复后的完整代码
下面是修复后的代码,我加上了详细的注释说明修改点:
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(void){ // 初始分配1个char*的空间(也可以初始分配0个,第一次循环再扩容) char **buf = malloc(sizeof(char*) * 1); if (buf == NULL) { // 增加malloc失败的检查 fprintf(stderr, "Initial malloc failed\n"); exit(-1); } for(int i = 0; i < 20; i++){ // 先扩容:确保buf有足够空间容纳i+1个char* char **temp = realloc(buf, sizeof(char*) * (i+1)); if(temp == NULL){ // 扩容失败时,必须先清理已分配的所有内存,避免泄漏 for(int j = 0; j < i; j++){ free(buf[j]); } free(buf); fprintf(stderr, "Realloc failed\n"); exit(-1); } buf = temp; // 更新buf为realloc返回的新地址 // 为当前字符串分配内存 buf[i] = malloc(sizeof(char) * 6); if(buf[i] == NULL){ // 检查单个字符串的分配失败 // 同样要清理已分配资源 for(int j = 0; j < i; j++){ free(buf[j]); } free(buf); fprintf(stderr, "String malloc failed\n"); exit(-1); } strcpy(buf[i], "hallo"); printf("%s\n", buf[i]); } // 程序结束前,释放所有分配的内存,避免泄漏 for(int i = 0; i < 20; i++){ free(buf[i]); } free(buf); return 0; }
关键修复点总结
- 调整扩容顺序:先执行
realloc扩容,再给buf[i]赋值,确保每次循环时buf的空间足够容纳当前需要的指针数量,彻底避免越界。 - 正确处理
realloc返回值:用临时变量接收realloc的结果,确认成功后再赋值给buf,防止原指针变成野指针。 - 完善错误处理:对所有内存分配操作的返回值做检查,并且在分配失败时清理已分配的内存,避免内存泄漏。
- 主动释放内存:程序结束前释放所有动态分配的内存,养成良好的内存管理习惯。
内容的提问来源于stack exchange,提问作者Qbongo
相关产品推荐
相关产品推荐

