You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

realloc(): Invalid next size错误求助,附C语言最小可复现示例

解决 realloc(): Invalid next size 错误的分析与修复

咱们一步一步拆解你代码里的问题,这个错误本质是内存越界破坏了堆结构,导致realloc无法正确识别内存块的管理元数据:

核心问题点

  • 未保存realloc的返回值
    realloc可能会分配新的内存块并释放旧块,或是在原地扩容。你现在的写法!realloc(buffer, bufsiz *= 2)不仅没把新地址赋值给buffer(原指针可能已失效),还会在realloc成功时触发return 1,逻辑完全搞反了。更糟的是,如果realloc失败返回NULL,你会丢失原buffer指针,造成内存泄漏。

  • 数组越界访问
    初始bufsiz=4,数组合法索引是0-3。当tmp == bufsiz时,tmp已经是4了,这时候buffer[tmp] = fgetc(stdin)会写入数组的第5个位置,直接越界破坏堆内存的管理信息——这就是realloc报错的直接原因。

  • fgetc返回值类型错误
    fgetc返回int类型,因为它要通过EOF(值为-1)表示文件结束。如果用char存储,当系统中char是无符号类型时,EOF会被转换成255,循环条件buffer[tmp] = fgetc(stdin)永远为真,会一直写内存直到越界崩溃。

  • 未处理malloc失败的情况
    如果malloc返回NULL,后续直接访问buffer[tmp]会导致未定义行为。

修复后的代码

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    size_t bufsiz = 4;
    char *buffer = malloc(bufsiz);
    // 处理malloc失败的情况
    if (!buffer) {
        perror("malloc failed");
        return 1;
    }

    int c;
    size_t tmp = 0;
    // 用int接收fgetc返回值,先判断是否为EOF
    while ((c = fgetc(stdin)) != EOF) {
        // 写入前检查空间,不足则扩容
        if (tmp >= bufsiz) {
            char *new_buf = realloc(buffer, bufsiz *= 2);
            if (!new_buf) {
                perror("realloc failed");
                free(buffer); // 避免内存泄漏
                return 1;
            }
            buffer = new_buf;
        }
        buffer[tmp++] = (char)c;
    }
    // 若需要将buffer作为字符串使用,可添加结束符
    // if (tmp < bufsiz) buffer[tmp] = '\0';

    free(buffer);
    return 0;
}

修复说明

  1. int c接收fgetc的返回值,正确识别EOF,避免循环无法终止。
  2. 先检查malloc是否成功,杜绝空指针访问。
  3. 在写入字符前检查空间,当tmp等于当前bufsiz时先扩容,彻底避免越界。
  4. 用临时指针接收realloc返回值,失败时释放原有内存,避免泄漏。
  5. 最后主动free内存,养成良好的内存管理习惯。

现在编译运行你的测试命令:

gcc prog.c -o prog
echo duck | ./prog

就不会再出现realloc相关错误了。

内容的提问来源于stack exchange,提问作者beardeadclown

火山引擎 最新活动