为啥这个函数返回垃圾值

Posted

技术标签:

【中文标题】为啥这个函数返回垃圾值【英文标题】:why does this function return garbage value为什么这个函数返回垃圾值 【发布时间】:2012-08-20 17:52:57 【问题描述】:

我正在编写一个程序,并面临以下函数用于返回垃圾值的问题:

int* foo(int temp)
   int x = temp;
   return &x;

当我修改它时,它工作正常:

int* foo(int *temp)
    int *x = temp;
    return x

第一个版本有什么问题?

【问题讨论】:

我不确定是否有 C 标记,但这个故事很有趣,而且是同样的问题:***.com/questions/6441218/… 【参考方案1】:

第一个版本返回对局部变量x 的引用,该变量的存储仅限于函数foo。当函数退出时,x 就不能再使用了。返回对它的引用是悬空指针的一个实例。

在第二个版本中,您实际上只是传入和返回相同的指针值,它指的是不受函数生命周期限制的内存。所以即使函数退出后,返回的地址仍然有效。

另一种选择:

int *foo(int temp)

    int *x = malloc(sizeof(int));
    *x = temp;
    return x;

【讨论】:

我不确定你的意思。您的意思是使用作为对象成员的变量吗? 如果你指的是结构或C++对象,这取决于它们是分配在堆栈上还是堆上。 当您打算返回一个指向整数的指针 (int*) 时,您要么需要在调用函数之前已分配成员,要么使用 malloc() 分配新内存。您应该永远不要将指向局部变量的指针作为函数输出返回 @pb2q 范围和存储持续时间是不同的东西,变量可以超出范围但它的存储仍然存在。 @ouah 我不相信我混淆了答案中的差异。如果我有,建议重新措辞?【参考方案2】:

对于每个函数,都会有一个激活记录,一旦该函数开始执行,就会在堆栈中创建该记录。激活记录也包含所有的局部变量。并且一旦函数执行完成,这个激活记录就会被释放。

因此,如果我们返回一个局部变量的地址,则意味着将释放先前函数的激活记录的内存。取消引用该内存是一种未定义的行为。

在下面的例子中,函数foo返回&x,这意味着p将保存func的局部变量x的地址。这是有效的。但是如果函数func 尝试返回无效的p(地址x)。

int* func

   int x;
   int *p;
   ...
   p = foo(&x);
   //using p is valid here
   ...
   return p; //This is invalid


int* foo(int *temp)

   int *x = temp;
   return x //This is valid

在以下情况下,函数foo 将其局部变量x 的地址返回给函数func。所以p 将保存foo 的局部变量的地址。所以推迟p是无效的,因为foo函数执行已经完成并且它的激活记录被释放了。

int* func

   int x;
   int *p;
   ...
   p = foo(x);
   //using p is invalid here
   ...
   return p; //This is invalid


int* foo(int temp)

   int x = temp;
   return &x; //This is also invalid

【讨论】:

以上是关于为啥这个函数返回垃圾值的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个函数会返回这个值? [复制]

为啥这个函数会返回一个值呢? (蟒蛇2.7)

MongoDB:为啥这个存储的 JS 函数没有返回值?

为啥这个函数在给定右值参数的情况下返回一个左值引用?

为啥 Rust 在 main 函数中没有返回值,以及如何返回值?

为啥我们应该总是从函数返回值?