char *a() {
char *t = malloc(8);
t[0] = 'a';
t[1] = 'b';
//...
t[7] = 'h';
return t;
}
int main(void) {
char *x = a();
//do something with x
//...
free(x);
return 0;
}
此代码是否存在任何潜在问题,因为内存已在a()
中分配并用于main()
中的内存?
答案 0 :(得分:10)
首先,a()被声明为返回void,但是您尝试返回char *。更改签名以返回char *。
其次,你的函数很好,但你的示例代码有内存泄漏,因为你永远不会释放返回指针所指向的内存。
第三,正如gbrandt指出的那样,在调用malloc之后,你没有检查是否成功。 malloc可能会失败,并检查它是否是一个很好的习惯。
实现此目的的另一种方法是将指针传递给指向()的指针,然后调用者必须在将指针传递给()之前自己创建指针,但无论哪种方式,您仍然需要释放记忆。说实话,在这种情况下,我会采用你的方法。没有令人信服的理由这样做,只是想我会提到它。
void a(char **p)
{
*p = malloc(8);
if (*p)
{
**p[0] = 'a';
**p[1] = 'b';
...
**p[7] = 'h';
}
}
int main(void)
{
char *x;
a(&x);
//do something with x
.....
free(x);
}
如果这种替代方法让您感到困惑,请告诉我,因为我很乐意提供解释(但目前,我需要重新开始工作!)
答案 1 :(得分:3)
以上所有好建议。代码的小问题,最重要的是......
您没有在malloc或函数调用后检查是否成功。不要忘记错误处理。
答案 2 :(得分:1)
没有问题 - 实际上,这是分配在函数返回后仍然可以使用的内存的正确方法 - 但是当你完成使用它时你可能想要free()
内存。八个字节不会成为问题,但编码内存泄漏是一个很好的习惯。
答案 3 :(得分:1)
除了a()
上的错误返回类型(应该是char *
而不是void
)之外,代码没有任何问题。
确保free()
完成后分配的内存。
答案 4 :(得分:1)
这里的大部分答案表明这不是问题,只需记住稍后释放()。这在技术上是正确的,但实际上是一个问题。无论何时在一个作用域中分配内存并期望它在另一个作用域中释放,您都会要求内存泄漏。人们不记得释放记忆。还有一个问题是调用者必须知道你使用了malloc而不是alloca()或new()或其他东西。如果他们调用除匹配的释放例程之外的任何内容,则结果是未定义的。
简而言之,分配内存并将其传递给调用者通常是错误的。
最好是期望调用者分配内存,因为如果他们分配内存,他们会记得释放它并正确地这样做。
答案 5 :(得分:0)
不,您不会明确地遇到任何问题,因为您在a
中分配了该功能并在main
中使用它。
答案 6 :(得分:0)
只要你记得释放x所指向的记忆,你就不会有任何问题。通过使用malloc(),您已经在堆上分配了内存,这在返回调用函数时是独立的。
答案 7 :(得分:0)
感谢。我刚刚编辑了代码。我猜这次应该没问题。顺便说一句,在C中,当一个函数完成时,编译器是否清除堆栈中的所有变量(包括数组和指针)?