作为this question的后续 Activity :
从我所看到的,这应该按预期工作:
void greet(){
char c[] = "Hello";
greetWith(c);
return;
}
但这会导致未定义的行为:
char *greet(){
char c[] = "Hello";
return c;
}
如果我是对的,那么修复第二个问候功能的最佳方法是什么?在嵌入式环境中?在台式机上?
最佳答案
你是绝对正确的。第二个示例中的c数组正在堆栈中分配,因此紧随其后的内存将被重用。特别是如果您有类似
printf("%s\n",greet());
您会得到奇怪的结果,因为对printf的调用会重用您数组的某些空间。解决方案是在其他地方分配内存。例如:
char c[] = "Hello";
char * greet() {
return c;
}
会工作。另一个选择是在范围内静态分配它:char * greet() {
static char c[] = "Hello";
return c;
}
因为静态内存是在数据空间中与堆栈分开分配的。第三种选择是通过malloc在堆上分配它:
char * greet() {
char * c = (char *) malloc(strlen("Hello")+1); /* +1 for the null */
strcpy(c, "Hello");
return c;
}
但是现在您必须确保以某种方式释放了内存,否则就会发生内存泄漏。更新资料
似乎比我预期的还要令人困惑的事情之一就是“内存泄漏”的确切含义。泄漏是指您动态分配内存但丢失了地址,因此无法释放它。这些示例中没有一个必然有泄漏,但是只有第三个示例甚至有可能泄漏,因为这是唯一动态分配内存的示例。因此,假设第三个实现,您可以编写以下代码:
{
/* stuff happens */
printf("%s\n", greet());
}
这有泄漏;返回指向已分配的内存的指针,printf
使用它,然后丢失;您将无法再释放它。另一方面,{
char * cp ;
/* stuff happens */
cp = greet();
printf("%s\n", cp);
free(cp);
}
不会泄漏,因为指针保存在自动变量cp
中的时间足够长,可以在其上调用free()
。现在,即使cp在执行结束后就消失了,但由于调用了free,因此内存已被回收并且没有泄漏。