将对象传递给函数时,为什么不必释放堆对象?

时间:2018-09-16 23:40:28

标签: c malloc free

以下程序没有内存泄漏。我的问题是,即使我同时分配了两个字符串,为什么也不必将str1和str2传递给free()?请在代码中我尝试释放str1和str2的地方看到两个注释的位置,取消注释该代码导致错误,提示我释放了一个非堆对象。但是据我了解,str1和str2是malloc创建的对象,因此是堆对象。我不明白这个矛盾。

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

char* StrCat(char* s1, const char* s2) {
    // Removing const from const char* s2
    //  made no difference on memory leak error message
    char *s, *tmp;
    s = tmp = malloc(strlen(s1) + strlen(s2) + 1);
    strcpy(tmp, s1);
    tmp += strlen(s1);
    strcpy(tmp, s2);
    //free(str1); free(str2); Why not?
    printf("%d\n", s[strlen(s)] == '\0'); // Prints 1
    return s;
}

int main(int argc, char** argv) {
    char* str1 = malloc(4 * sizeof (char));
    str1 = "abc\n";
    char* str2 = malloc(6 * sizeof (char));
    str2 = "party\n";

    char* new = StrCat(str1, str2);
    //free(str1); free(str2); Why not?
    printf("%s\n", new);
    free(new); // Required
    return 0;
}

1 个答案:

答案 0 :(得分:1)

当然,无论是否将其传递给函数,都需要释放堆对象。无论malloc()返回什么,最终都必须free(),无论您将如何使用它。

您的问题如下:

以下行:

char* str1 = malloc(4 * sizeof (char));

为4个字符分配内存,并将对它的引用存储在str1中。

以下行:

str1 = "abc\n";

忘记str1指向的任何内存(从而导致内存泄漏),并使str1指向程序的静态数据段中的新位置。这是从未分配过的内存,因此可能无法释放。

为了解决您的问题,而不是将str1设置为指向"abc\n"的情况,您需要使用strcpy()"abc\n"复制到指向的已分配存储块中由str1

在执行此操作之前,请不要忘记将46分别增加1,因为C中的字符串还包含一个以零结尾的字节,因此您需要为{{ 1}}和5个字符。