【问题标题】:Return address of local variable in CC中局部变量的返回地址
【发布时间】:2012-01-05 13:34:57
【问题描述】:

假设我有以下两个功能:

1

int * foo()
{
  int b=8;
  int * temp=&b;
  return temp;
}

2

int * foo()
{
   int b=8;
   return &b;
}

我没有收到第一个警告(例如 函数返回局部变量的地址)但我知道这是非法的,因为 b 从堆栈中消失了,我们只剩下指向未定义内存的指针。

那么我什么时候需要小心返回临时值的地址呢?

【问题讨论】:

    标签: c return return-value


    【解决方案1】:

    您在第一个 sn-p 中没有收到警告的原因是因为您没有(从编译器的角度)将地址返回给局部变量。

    您正在返回int * temp 的值。即使这个变量可能(并且在这个例子中是)包含一个值,该值是一个局部变量的地址,编译器也不会向上代码执行堆栈查看是否是这种情况。

    注意两个 sn-ps 都同样糟糕,即使您的编译器没有警告您前者。不要使用这种方法。


    将地址返回给局部变量时应始终小心;通常,您可以说您从不应该这样做。

    static 变量是一个完全不同的情况,this thread 正在讨论。

    【讨论】:

    • 谢谢!当我在 main 中打印返回值时,它会得到正确的结果,这实际上意味着它打印的是垃圾?
    • 表示你在调用我们通常所说的undefined behavior,即。标准中未指定的行为。
    【解决方案2】:

    我会说你可以返回局部变量或更确切地说是指向这样的指针,如果它是由 malloc 动态分配的,在这种情况下,用于存储变量的内存要在堆栈上但在堆上,并且不会被清除或重新-在退出函数后使用,因为它发生在自动局部变量的情况下(在没有 malloc 的情况下创建),对吗?

    【讨论】:

      【解决方案3】:

      这两个例子同样不正确。我的猜测是您的编译器没有看到危险,因此当您将地址存储在临时变量中时不会发出警告。

      【讨论】:

        【解决方案4】:

        这个问题可能是 StackO 上讨论最多的问题之一。下面是来自 StackO 上类似线程的两个回复,我觉得这很有趣,并且可能让我放弃了取消引用局部变量的这种不良做法,尽管我得到错误(未定义行为)的可能性非常小。

        Here is a simple answer

        我特别喜欢这个回复。

        Here is an example where this bad practice caused some real hardware damage

        【讨论】:

          【解决方案5】:

          这些都很糟糕,一个好的编译器应该能够检测到这两种情况并发出警告。通过将警告级别调到最大(无论如何您都应该这样做)并开启优化,您可能会获得更好的结果。

          【讨论】:

          • 具体情况,也许吧。但是有很多类似的情况涉及将地址与其他变量(或通过其他函数)进行混洗,而编译器根本无法检测到。此外,优化很少会增加检测到此类问题的机会 - 它只会增加问题产生可观察影响的机会。
          • 当然有些情况编译器无法检测到,但这些特定情况应该很容易检测到。优化之所以有效,是因为它将第一个示例减少到第二个。
          • 对不起,不是真的。当谈到编译器的实现质量时,几乎没有“应该”——这些是供应商基于他们自己的成本/收益分析做出的决定,这可能不符合开发人员的先入之见。构建示例(例如,可能更改指针的函数调用)也很容易,这意味着您声称的优化可能不可行——这也使得供应商决定是否优化这些东西,而不是给定的。
          • 当然,优化不是标准的一部分,因此完全取决于供应商。但是,任何无法在此示例中优化掉不必要的临时的编译器都是毫无价值的。另外,如果您阅读了我的回答,它会说“您可能会获得更好的结果...”祝您有美好的一天。
          猜你喜欢
          • 2014-04-12
          • 2011-10-17
          • 2021-04-28
          • 1970-01-01
          • 2013-01-30
          • 1970-01-01
          • 2014-05-14
          相关资源
          最近更新 更多