You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C实现readLine跳出while循环报realloc invalid next size错误

问题根因

你代码里有4个确定性bug,直接导致所有异常现象:

    1. 循环逻辑运算符使用错误,造成永真循环
      循环判断条件写为(c = getchar()) != '\n' || c != EOF,逻辑或||的规则是只要任意一个子条件为真,整体条件就为真。没有任何字符能同时等于'\n'和EOF,所以这个条件永远为真,循环永远不会主动退出。
      读完输入的可见字符和换行符后,循环还会继续运行:要么持续等待新输入,要么在读到EOF后反复把EOF值写入缓冲区,很快越过malloc申请的内存边界写数据,破坏glibc malloc用于管理堆内存的元数据(chunk头),这就是realloc(): invalid next size错误的核心来源——堆结构已经被越界写损坏,后续任何内存分配/释放操作(包括printf内部隐含的堆操作)都会触发内存校验失败,直接abort进程。
      你之前误以为不是死循环,是因为循环内加了位置打印能看到pos递增,实际上这就是越界写正在发生的表现。
    1. 存储getchar返回值的变量类型错误
      getchar()的返回值类型是int,合法返回值要么是0-255的无符号字符值,要么是EOF(通常为int类型的-1)。用char类型变量c存储返回值会发生类型截断:
    • 如果运行环境下char是无符号类型,EOF(-1)会被转换为255,永远和int类型的EOF不相等,无法正确识别输入结束
    • 如果运行环境下char是有符号类型,读到值为0xff的扩展ASCII字符时会被误判为EOF,提前截断输入
    1. 内存分配逻辑存在隐患
      malloc申请内存时乘了sizeof(char),但realloc扩容时直接传了buffsize数值,虽然sizeof(char)标准规定为1不会造成当前逻辑的大小错误,但属于不规范写法;同时直接把realloc返回值赋值给原buffer指针,如果realloc分配失败返回NULL,原buffer的地址会丢失造成内存泄漏,也没有对realloc的返回值做合法性校验。
    1. 输出和字符串构造逻辑错误
    • printf("exited");没有加换行符,也没有手动fflush刷新标准输出,而stdout默认是行缓冲模式,没有遇到换行符时内容会暂存在缓冲区不输出到屏幕,哪怕代码执行到了这行你也看不到输出,误以为代码没走到
    • 读取完字符后没有在缓冲区末尾添加C字符串要求的终止符'\0',返回的buffer不是合法C字符串,后续用字符串处理函数操作时会触发越界读。
修复后的完整代码
// 建议将shbuffsize设置为1024这类合理值
#define shbuffsize 1024

// 保持你之前实现的内存分配检查函数即可
int CheckMallocError(void *ptr, const char *desc);

char *readLine(void){
    int buffsize = shbuffsize;
    char *buffer = malloc(sizeof(char) * buffsize);
    // 修正c的类型为int,匹配getchar返回值
    int c;
    int pos = 0;

    if(CheckMallocError(buffer, "buffer")){
        exit(EXIT_FAILURE); 
    }

    // 修正逻辑运算符为&&:读到换行符*或*读到EOF时退出循环
    while ((c = getchar()) != '\n' && c != EOF) {
        // 预留1字节存最后的终止符'\0'
        if(pos >= buffsize - 1){
            buffsize += shbuffsize;
            // 用临时指针存realloc返回值,避免分配失败丢失原指针
            char *new_buf = realloc(buffer, sizeof(char) * buffsize);
            if(CheckMallocError(new_buf, "realloc buffer")){
                free(buffer); // 释放原内存避免泄漏
                exit(EXIT_FAILURE);
            }
            buffer = new_buf;
        }

        buffer[pos] = (char)c;
        pos++;
    }

    // 补充字符串终止符
    buffer[pos] = '\0';
    // 加换行自动刷新输出缓冲区
    printf("exited\n");
    return buffer;
}
额外说明
  • 加break后依然报错的核心原因:无break版本运行时已经发生堆越界写,永真循环会在你无感知的情况下持续写内存,只要多跑几轮就会越过缓冲区边界破坏堆结构,哪怕后续break出循环,调用printf这类隐含堆操作的函数时依然会触发内存校验失败。
  • 测试功能时,readLine返回的buffer使用完后记得调用free()释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:18:24