多次调用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
相关产品推荐
相关产品推荐

