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

C语言动态输入函数触发corrupted size vs. prev_size错误排查

错误根因

corrupted size vs. prev_size是glibc堆校验抛出的错误,本质是堆块的头部元数据被越界写破坏,你的代码有两个必触发的逻辑bug:

  • C语言函数参数是值传递,dynInput的形参text是main中指针的拷贝,函数内部执行realloc后得到的新内存地址,只会修改这个局部拷贝,main里的text永远指向最开始malloc返回的旧地址。一旦realloc因为原块后续空间不足、把内存移到新位置,旧地址就成了野指针,后续读写全是非法内存访问。
  • 内存读写和扩容顺序完全写反了:你每次都是先往text[i]写字符,再扩容到l字节大小。初始l=1,第一次循环写完text[0]再扩到1字节还能凑活;第二次循环i=1时,你还没扩容就写text[1],此时内存块实际只有1字节大小,直接越界写覆盖了堆块保存元数据的区域,输入超过十几个字符后,堆结构破坏累积到触发校验阈值,就会抛出你看到的错误。
  • 额外隐患:getchar()返回值是int类型,专门用来和EOF做区分,你直接存到char里,遇到输入终止(Ctrl+D/Ctrl+Z)时会进入死循环。
修复方法
  1. 把dynInput的参数改成二级指针char**,传入main中text指针的地址,保证函数内部能修改外层的指针值,拿到realloc返回的新地址
  2. 调整操作顺序:先确认剩余空间足够,再写入字符,同时预留字符串结束符\0的位置
  3. 增加EOF判断,避免异常死循环
  4. 把逐字节扩容改成倍数扩容,减少realloc调用次数,提升性能

修复后可直接运行的代码:

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

void dynInput(char **text);

int main()
{
    char *text = malloc(sizeof(char));
    if (text == NULL) return 1;
    while(1)
    {
        dynInput(&text);
        if (text[0] == '\0' && feof(stdin)) break;
        printf("%s\n", text);
    }
    free(text);
    return 0;
}

void dynInput(char **text)
{
    int c;
    int str_len = 0;
    int cap = 1; // 初始容量和main中分配的1字节对应
    while ((c = getchar()) != '\n' && c != EOF)
    {
        // 需要存当前新字符+末尾的'\0',容量不够就先扩容
        if (str_len + 2 > cap)
        {
            cap *= 2;
            char *tmp = realloc(*text, cap);
            if (tmp == NULL)
            {
                free(*text);
                exit(EXIT_FAILURE);
            }
            *text = tmp;
        }
        (*text)[str_len++] = (char)c;
    }
    (*text)[str_len] = '\0';
}
补充说明
  • 原代码每次只扩1字节的写法效率极低,每次写入都要触发内存分配,2倍扩容是动态数组的常规实现,性能表现好很多
  • 所有内存分配操作都加了空指针判断,避免分配失败时的空指针引用
  • 程序退出前主动释放申请的内存,避免运行时内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:00:53