作为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,因此内存已被回收并且没有泄漏。

10-08 05:48