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

C语言中free()调用后字符串指针出现乱码的问题求解

C语言malloc/realloc/free使用问题排查与解决

我接触C语言不到两个月,最近在使用malloc、realloc和free时遇到了问题。我写了一个print_num函数,功能是把整数转成字符串后打印,count用来记录打印的字符数,代码如下:

int print_num(int num, int count)
{
    int i = 0, len;
    char last, *ptr2, *ptr = (char *)malloc(sizeof(char));

    if (num == 0)
        return (print_char('0', count));
    if (num < 0)
        count = print_char('-', count);
    num = abs(num);
    while (num != 0)
    {
        last = (num % 10) + '0';
        if (i == 0)
            *(ptr) = last;
        else
        {
            ptr2 = (char *)realloc(ptr, i + 1);
            *(ptr2 + i) = last;
            ptr = ptr2;
        }
        num /= 10;
        i++;
    }
    len = strlen(ptr);
    for (i = len; i > 0; i--)
        count = print_char(ptr[i - 1], count);
    free(ptr);
    return (count);
}

问题是:如果不调用free(ptr)或free(ptr2),代码运行正常,但多次调用这个函数时,字符串指针ptr末尾会出现乱码。比如连续调用两次:

print_num(39, 0);
print_num(39, 0);

得到的输出是:

Length:[39, U�39]

删掉free(ptr)后代码正常,但会造成内存泄漏,请问该怎么解决?

附print_char函数实现:

int print_char(char c, int count)
{
    write(1, &c, 1);
    return (count + 1);
}

问题根源

你的代码有两个核心问题:

  • 分配的内存没有以空字符'\0'结尾:strlen依赖字符串末尾的'\0'来计算长度,你用malloc/realloc分配的内存只存储了数字字符,没有添加终止符,导致strlen会读取到内存里的随机垃圾数据,出现乱码。
  • 未检查内存分配失败的情况:malloc和realloc都可能返回NULL,直接使用会导致程序崩溃,这个隐患必须处理。

修复方案

基础修复版(保留原逻辑)

核心是给字符串添加终止符,同时检查内存分配结果:

int print_num(int num, int count)
{
    int i = 0, len;
    char last, *ptr2, *ptr = (char *)malloc(sizeof(char));

    // 检查malloc是否成功
    if (ptr == NULL)
        return count;

    if (num == 0)
    {
        free(ptr); // 提前释放分配的内存
        return print_char('0', count);
    }
    if (num < 0)
        count = print_char('-', count);
    num = abs(num);
    
    while (num != 0)
    {
        last = (num % 10) + '0';
        if (i == 0)
        {
            *ptr = last;
        }
        else
        {
            ptr2 = (char *)realloc(ptr, i + 1);
            if (ptr2 == NULL) { // 检查realloc是否成功
                free(ptr);
                return count;
            }
            *(ptr2 + i) = last;
            ptr = ptr2;
        }
        num /= 10;
        i++;
    }
    // 关键:重新分配内存,添加字符串终止符
    ptr2 = (char *)realloc(ptr, i + 1);
    if (ptr2 != NULL) {
        ptr = ptr2;
    }
    ptr[i] = '\0'; // 写入终止符
    
    len = strlen(ptr);
    for (i = len; i > 0; i--)
        count = print_char(ptr[i - 1], count);
    
    free(ptr);
    return count;
}

优化版(减少内存分配次数,避免溢出)

可以提前计算数字的位数,一次性分配足够内存,还能解决abs(INT_MIN)的溢出问题(INT_MIN的绝对值超过int的范围):

int print_num(int num, int count)
{
    int temp = num;
    int digits = 0;
    char *ptr;
    int i;

    if (num == 0)
        return print_char('0', count);
    
    // 处理负数,用-temp代替abs避免INT_MIN溢出
    if (num < 0)
    {
        count = print_char('-', count);
        temp = -temp;
    }
    
    // 计算数字的位数
    while (temp != 0)
    {
        digits++;
        temp /= 10;
    }
    
    // 一次性分配内存,包含终止符的位置
    ptr = (char *)malloc(digits + 1);
    if (ptr == NULL)
        return count;
    
    temp = num < 0 ? -num : num;
    i = digits;
    ptr[i] = '\0'; // 先写入终止符
    
    // 从后往前填充数字字符
    while (temp != 0)
    {
        i--;
        ptr[i] = (temp % 10) + '0';
        temp /= 10;
    }
    
    // 直接从前往后打印,无需反转
    for (i = 0; ptr[i] != '\0'; i++)
        count = print_char(ptr[i], count);
    
    free(ptr);
    return count;
}

说明

  • 基础修复版保留了你原有的逻辑,只补充了终止符和内存检查,适合你理解原有代码的问题。
  • 优化版更高效,避免了多次realloc的开销,还处理了边界情况,是更健壮的实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:18:03