【问题标题】:Why does not the "Warning C4172 returning address of local variable or temporary" error occur?为什么不出现“Warning C4172 return address of local variable or temporary”错误?
【发布时间】:2018-08-22 06:45:03
【问题描述】:

这段代码,返回一个局部指针变量。

但是,为什么没有出现“Warning C4172 return address of local variable or temporary”错误呢?

编译器不输出任何错误。

#include<stdio.h>

static const char *test(void){
    const char *a = NULL;
    char b[64] = {0,};
    a = b;
    return a;

}

int main() {
   const char *a;
   a = test();
}

【问题讨论】:

  • 显然编译器并没有传递 b 是 a 本地的信息。 (b 指向的内存可以动态分配;如果您返回&amp;a(更改函数签名后),您肯定会收到警告。)顺便说一句,gcc 也不会抱怨。
  • 安全网只能伸展到这里……
  • clang 编译器似乎检测到了这个问题:`警告:与返回给调用者的局部变量 'b' 关联的堆栈内存地址`
  • @StoryTeller 我希望优化器完全消除a。如果优化器可以看到这些东西,编译器也可以通过可接受的努力,至少有一个选项(这样我们就不会降低已知良好程序的编译时间)。
  • @PeterA.Schneider - 另一方面,优化器可以将此程序减少到相当于return 0; - 因此,如果它返回到它,可能没有任何东西可以诊断。跨度>

标签: c memory-management


【解决方案1】:

C 中有两种“错误”(我在这里非常松散地使用术语错误)。 必须在编译时捕获并且编译器有义务发出诊断的错误。在这种情况下,不能创建可执行文件。

例如:

int foo() int
{
    return 24
}

上面的sn-p代码不是C程序,不能编译。

另一种是运行时错误。虽然这里有几个,但我将专注于未定义的行为。其中某些部分的某些程序具有这样的语义:如果它们被执行,则程序的行为是未定义的。而且,需要注意的是,标准规定:“无需诊断”。

让我们举一个与你相近的例子:

int* foo()
{
    int a;
    return &a;
}

这在技术上是合法的。使用指针是非法的。例如,如果您的程序在任何时候这样做:

int* x = foo();
*x = 24;

那么你的程序有未定义的行为。并且编译器不需要发出任何诊断。之所以如此,是因为在实践中检查 UB 会变得非常困难、不可能或性能损失很大。

另一方面,如果您的程序从不使用来自foo() 的指针,那么一切正常。但是由于返回的指针实际上是无用的并且很可能是一个错误,因此大多数编译器会尝试检测这种情况并在编译时发出警告。只是碰巧分析不够深入或复杂,无法在您的特定情况下检测本地地址的返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    相关资源
    最近更新 更多