C语言中的数组及其指针

5

虽然这个问题已经过时,但我还是有一些想法。

char * getarrmal(void)
{
    char *str;
    str = (char *)malloc(10);
    str[0] = 'a';
    str[1] = 'b';
    str[2] = 'c';
    str[3] = '\0';
    return str;
}

char * getarrdef(void)
{
    char *str = "hello";
    return str;
}

char * getarrfix(void)
{
    char str[10] = "world";
    return str;
}

有三个函数。 前两个函数将返回一个字符串地址,该字符串存储在堆上,因此您可以在例如main()函数中继续使用它。

在最后一个函数中,str是一个局部变量,返回的str不能被使用。

我的问题是,在调用前两个函数的函数中返回时,我是否应该手动释放它们? 对于malloc情况来说,很容易相信这是真的,但我不确定对于char * str =“hello”也是如此。

如果我使用getarrdef()并且不释放其返回值,那么会出现内存泄漏吗?


3
如果你已经分配了它,而且你没有使用malloc(或其相关函数)来进行分配,那么你就不需要调用free。很简单。 - Ed S.
1个回答

4
不,你绝对不应该尝试释放第二个。它并没有存储在堆中,而是一个字符串常量,尝试释放它会导致未定义的行为。引用自:
“……如果参数与早期由内存管理函数返回的指针不匹配,或者空间已被调用free或realloc释放,则行为未定义。”
对于第一个变量,将负责分配的内存责任随着内存本身一起传递是良好的实践。这意味着如果某些东西分配了它并把它交给你,那么你就负责释放它。
即使通过将其传递回一个名为delarrmal()的函数来释放它 - 这样做,你已经将释放的责任交给了那个函数。

谢谢您的快速回复:)。那么第二个函数中的str存储在哪里有点有趣,是调用者的堆栈吗? - coldguy
2
@coldguy,前两种情况下,str(指针)存储在堆栈中,第三种情况下存储str(数组)。然而,在前两种情况下,指针所指向的内容是不同的(第三种情况不相关,因为str不是指针(函数内部))。在第一种情况下,它指向堆,而在第二种情况下,它指向不在堆中的字符串字面量。 - paxdiablo
或者,第二个函数将是最佳实践。您可以返回一个字符串,而无需担心其内存分配。听起来很棒... - coldguy
@coldguy,第二种情况的问题在于您无法“修改”字符串。如果您不需要,那很好。但是许多情况下都需要这样做。Jim,我必须反对“分配器函数应该释放内存”,因为在需要在调用者中使用已分配的内存的情况下,跟踪内存的责任是防止双重释放或泄漏的绝佳方法。 - paxdiablo
有责任跟踪内存意味着您必须跟踪责任,而人们会犯错。(例如,unique_ptr 就是为了让编译器跟踪它,以便您不会犯错。)这也意味着被调用者必须知道内存是如何分配的,这被称为“耦合”,这是一种反原则。在分配内存的同一模块中释放内存是封装的体现。在 C++ 中,这体现在 RAII 原则中。虽然我为什么要向 C 程序员 讲述基本的软件工程原则,并且还是在评论线程中,这超出了我的理解范围。我想我最好停止了。 - Jim Balter
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接