将函数从函数返回到另一个函数后,是否必须释放动态分配的数组?

时间:2017-02-26 16:39:24

标签: c arrays

考虑以下功能:

char* color(const char* clr, char* str)
{
    char *output = malloc(strlen(str)+1);

    /* Colorize string. */
    sprintf(output, "%s%s%s", clr, str, CLR_RESET);

    return output;
}

上述功能允许我们在linux终端中打印彩色消息。

所以我可以写

printf("%s", color(CLR_RED, "This is our own colorized string"));

并以红色显示消息This is our own colorized string

我关注的是output中分配的color()字符串。当函数返回一个已分配的元素(在我们的示例中为数组)时,我们需要释放它(C没有垃圾收集器)。

我的问题是,output之后会发生什么?printf()?当我们退出函数printf()时,仍然会分配数组?如果是,我们如何解除分配?有没有办法编写一个为我们这样做的函数?

提前致谢!

3 个答案:

答案 0 :(得分:9)

首先,您的代码是错误的。您拨打malloc时尺寸太小,因此会有buffer overflow。你忘了测试malloc的失败。你可能应该编码:

char *output = malloc(strlen(clr)+strlen(str)+strlen(CLR_RESET)+1);
if (!output) { perror ("malloc in color"); exit(EXIT_FAILURE); }
sprintf(output, "%s%s%s", clr, str, CLR_RESET);
BTW,有些系统有asprintfuse会更容易)。使用sprintf的恕我直言是危险的(你应该更喜欢snprintf)。

然后,C编程需要很多约定。你应该拥有你的(灵感来自惯常做法)。我建议您研究现有的free software源代码(例如来自github),以获取灵感。

你可以让一个函数返回一个malloc - ed指针,但你需要记录这个约定(至少,作为公共头文件中的注释声明 color)并明确规定在其结果上调用free的义务,并在其他地方跟踪。

然后,在调用 color的函数中,您将free的结果调用color

一般情况下,您应该在调用 free之后malloc指针值来获取它(但当然要照顾pointer aliases),但只有一次指针(更确切地说是指向它的内存区域)是没用的。

不要忘记启用所有警告&编译时调试信息(如果使用GCC,则为gcc -Wall -g)。使用调试器(gdb)。使用memory leak之类的valgrind检测器。

您应该阅读更多关于C dynamic memory allocation&的内容。 virtual address space

如果在Linux上,请同时阅读Advanced Linux Programming。阅读Operating SystemsGarbage Collection将会有所帮助(至少对于相关概念而言)。

答案 1 :(得分:3)

  

我的问题是,传递到输出后会发生什么   printf()的?当我们退出函数printf()时,数组仍然是   分配呢?如果是,我们如何解除分配?有什么办法吗?   写一个为我们这样做的函数?

是的,在color函数结束后,您为output分配的内存仍然存在。您需要存储color函数的返回值,并在完成使用后调用free

是的,正如另一个答案所述,在这种情况下,传递给malloc的大小很小。

你可以完全避免使用malloc。 在调用者代码中声明一个字符串,例如

char someStr[100];

并传递给您的色彩功能

void color(char* output, const char* clr, char* str)
{
    /* Colorize string. */
    sprintf(output, "%s%s%s", clr, str, CLR_RESET);
}

在这里,不再需要malloc了。

致电:color(someStr, CLR_RED, "This is our own colorized string")

答案 2 :(得分:0)

另一种方法是使用全局缓冲区char [whatever]:不需要alloc(),不需要free()。 color()函数始终返回该缓冲区。唯一可能是非问题的问题是,color()将 NOT 可重入,并且每个语句只能调用一次。

char g_color_buf[200];

char* color(const char* clr, char* str) {
    sprintf(g_color_buf, "%s%s%s", clr, str, CLR_RESET);
    return g_golor_buf;
}

更新:从下面的评论中,最好将g_color_buf []声明为函数本身内的static,而不是污染全局命名空间。这样做并不能解决其他问题,但无论如何都会更好。

如上所述,此例程不应用于以下语句中:

printf("%s %s", color(CL_WHITE, "Result:"), color(CL_RED, "Error"));

因为第二次调用color()会破坏第一次调用所做的工作。

最后,回答你的问题(需要,因为否则有人可以说&#34;你没有回复&#34;),你的示例代码中由color()分配的内存将保持在那里直到<你> (没有其他人)会释放它。考虑到你可能想要的平均正常使用,多次写作会很不舒服:

tmp = color(CL_RED, "hello");
printf("%s", tmp);
free(tmp);

使用全局缓冲区传递给color()的解决方案,也许还有它的大小,如:

printf("%s", color(buffer1, CL_RED, "Hello"));
--or--
printf("%s", color(buffer2, sizeof(buffer2), CL_RED, "HelloHello"));

肯定是最正确的,但很无聊。好吧,如果你愿意打字就不无聊了!