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

多次调用C语言函数释放动态内存后程序输出空白问题求助

动态内存管理问题:多次调用函数后输出空白且无内存泄漏的解决方案

问题描述

编写了Func函数,接收动态分配的字符串,返回修改后的新动态字符串,函数内会释放传入的输入指针。但在main中多次调用B = Func(B, n)后,程序输出空白;若省略free(input)或不多次调用函数,程序可正常运行但存在内存泄漏。需要在不使用额外指针、不产生内存泄漏的前提下解决该问题。

原代码

// ACTUAL CODE
// To simplify this example, I am just reducing the string instead of modifying it.
// But everything else is the same

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

char *Func(char *input, int n) {

    char *output = (char *)malloc(n * sizeof(char));

    // populate output with parts from input.
 
    for (int i = 0; i < n; i++)
    {
        output[i] = input[i];
    }
    output[n] = '\0'; 
    // output is now a valid string.

    free(input); 
    // PROBLEM AREA 1
    // If this command is omitted, the program works fine even with PROBLEM AREA 2.

    return output;
}

int main(int argc, const char *argv[]) {

    char *A = (char *)malloc(100 * sizeof(char));
    puts("Enter string:");
    gets(A);

    char *B;

    B = Func(A, 80);
    // B is now pointing to memory that was pointed to by output in this Func(A) call.

    B = Func(B, 77);
    B = Func(B, 62);
    // PROBLEM AREA 2
    // B should point to memory pointed by new output in Func(B) call. Earlier memory of B should have been
    // freed by the free(input) command within Func(). 
    // But B appears to be blank, I suspect due to free(input) within Func().
    // If I don't call multiple times, program works fine. Even with PROBLEM AREA 1.

    printf("%s\n", B); // print whatever string is at B to screen.

    free(B); 
    B = NULL;
    //Since B is pointing to dynamic memory and I no longer need B.

    return 0;
}

预期与实际结果

  • 预期:无论调用B = Func(B,n)多少次,都能输出缩短后的字符串。
  • 实际:程序输出空白行,编译无错误。
  • 注意:仅当同时保留free(input)和多次调用函数时程序失效,省略其一可正常运行但存在内存泄漏。

问题根源

核心错误是内存越界写入:
Func中malloc(n * sizeof(char))只分配了n个字符的内存空间,但后续执行output[n] = '\0'时,访问了超出分配范围的内存(数组下标从0到n-1,n是越界位置)。这种越界会破坏堆内存的管理结构,导致后续的free和malloc操作出现异常。第一次调用Func时的越界已经损坏了堆,后续多次调用时,内存分配和释放的逻辑彻底混乱,最终导致B指向的内存无效,输出空白。

解决方案

修改Func中的malloc语句,分配n+1个字符的空间,预留出存储字符串终止符'\0'的位置:

char *output = (char *)malloc((n + 1) * sizeof(char));

修正后的完整代码

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

char *Func(char *input, int n) {
    // 分配n+1个字符空间,用于存储n个字符+终止符
    char *output = (char *)malloc((n + 1) * sizeof(char));
    if (output == NULL) {
        // 新增malloc失败判断,避免空指针操作
        free(input);
        return NULL;
    }

    for (int i = 0; i < n; i++) {
        output[i] = input[i];
    }
    output[n] = '\0'; 

    free(input); 
    return output;
}

int main(int argc, const char *argv[]) {
    char *A = (char *)malloc(100 * sizeof(char));
    if (A == NULL) {
        return 1;
    }
    puts("Enter string:");
    gets(A);

    char *B = Func(A, 80);
    if (B == NULL) {
        return 1;
    }
    B = Func(B, 77);
    B = Func(B, 62);

    printf("%s\n", B);

    free(B); 
    B = NULL;

    return 0;
}

说明

  • 修正后,内存分配足够存储截断后的字符串和终止符,不会再出现越界写入问题,堆内存结构保持完整,多次调用Func时的free和malloc操作都能正常执行。
  • 新增了malloc失败的判断,避免空指针操作导致的程序崩溃,提升鲁棒性。
  • 既保证了无内存泄漏(每次传入的旧指针都被正确释放),也无需额外指针,满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:47:18