考虑以下功能:
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()
时,仍然会分配数组?如果是,我们如何解除分配?有没有办法编写一个为我们这样做的函数?
提前致谢!
答案 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,有些系统有asprintf(use会更容易)。使用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 Systems和Garbage 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"));
肯定是最正确的,但很无聊。好吧,如果你愿意打字就不无聊了!