我试图在C中创建一种toString
函数,如下所示:
struct esploratore {
char nome[20];
char cognome[20];
int nascita;
int morte;
};
char *esploratoreToString(esploratore e) {
char *s = (char*) malloc(50 * sizeof(char));
snprintf(s, 50,
"%s %s %d %d",
e.nome, e.cognome, e.nascita, e.morte);
return s;
}
并以这种方式在main
中使用:
printf("%s", esploratoreToString(e));
它是有效的,但问题是:malloc分配的内存会被释放吗?
这是唯一的解决方案吗?
char *s = esploratoreToString(e);
...
printf("%snn", s);
free(s);
在原始代码中,内存不会被释放。这是内存泄漏。
要正确调用此函数,您必须执行
char *s = esploratoreToString(e);
printf("%s", s);
free(s);
如果要让esploratoreToString
进行分配,那么实际上没有任何方法可以解决这个问题。C中动态分配的对象永远不会释放自己。(C++是另一回事…(
(当然,esploratoreToString
应该在继续之前检查malloc
是否成功…(
是。这是C中常见的习惯用法:被调用者分配内存,将所有权转移给调用者。这意味着调用者现在负责释放分配的块。
malloc()
分配的内存在调用free()
时释放,否则在进程退出时将释放。作为目前的设计,调用代码负责在使用完内存后释放内存。或者,您可以重新设计exploratoreToString()
,以提供缓冲区及其大小作为参数。
有一种替代方案,您可以在其中提供缓冲区:
char *esploratoreToString(esploratore *e, char *buf, int bufsz) {
snprintf(buf, bufsz,
"%s %s %d %d",
e.nome, e.cognome, e.nascita, e.morte);
return buf;
}
...
int main()
{
char buf[100];
esploratore exp = {...};
printf("%sn", esploratoreToString(&exp, buf, sizeof buf);
}
因此,您可以动态地分配它,或者作为一个自动堆栈分配的缓冲区。
另一种选择是返回一个指向静态分配的缓冲区的指针,如:
char *esploratoreToString(esploratore *e) {
static char buf[50];
snprintf(buf, bufsz,
"%s %s %d %d",
e.nome, e.cognome, e.nascita, e.morte);
return buf;
}
但这有一个问题,即它是不可重入的,而且如果你需要在对printf(3)
的同一次调用中调用它两次(在main
中(,第二次调用将覆盖缓冲区,并且你会得到一个奇怪的行为,因为用下一个结果覆盖一个结果,并打印两次相同的东西。