编译器检测返回对局部变量的引用

发布于 2024-09-19 08:47:45 字数 764 浏览 2 评论 0原文

由于返回对局部变量的引用,我刚刚被一种令人讨厌的未定义行为所困扰。

我们知道它是邪恶的,通常编译器会打印一个漂亮的警告来告诉我们……不过,gcc (3.4.2) 似乎并没有将检查推得太远。

std::string get_env_value(std::string const& key);

std::string const& get_phase()
{
  std::string const& phase = get_env_value("PHASE"); // [1]
  std::cout << "get_phase - " << phase << '\n';
  return phase;                                      // [2]
}

编译没有出现任何问题,但我们却陷入了未定义行为的令人讨厌的领域。

[1] 行是可以的,因为标准指定绑定到 const 引用的变量的生命周期应该延长以匹配 const 引用的生命周期。

[2] 行似乎也可以...

  • C++ 规范是否涵盖这种情况?
  • 有谁知道这是否通常被诊断出来? (我可能会错过一个标志或其他东西......)

在我看来,静态分析应该能够告诉我们对 [1][2] 使用了“生命周期扩展” 并不安全,但我猜它可能会很快变得丑陋......

I've just been bitten by a nasty undefined behavior due the returning a reference to a local variable.

We know it's evil, and generally the compiler prints a nice warning to tell us so... well gcc (3.4.2) does not seem to push the checks too far though.

std::string get_env_value(std::string const& key);

std::string const& get_phase()
{
  std::string const& phase = get_env_value("PHASE"); // [1]
  std::cout << "get_phase - " << phase << '\n';
  return phase;                                      // [2]
}

This compiles without a glitch, and yet we fall in the nasty realm of undefined behavior.

Line [1] is okay because the standard specifies that the lifetime of a variable bound to a const reference should be extended to match the lifetime of the const reference.

Line [2] seems okay too...

  • Do the C++ specifications cover this case ?
  • Does anyone know if this is usually diagnosed ? (I may miss a flag or something...)

It seems to me that static analysis should be able to tell that having use a "lifetime extension" for [1], [2] is not safe, but it could get ugly rapidly I guess...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˉ厌 2024-09-26 08:47:45

该标准不涵盖[2]。它允许将右值绑定到 const 引用,但这不允许您返回 const 引用并延长其所绑定的右值的生命周期。

确实,静态分析可以抓住这一点,但一如既往,这是一种权衡。 C++ 编译本身就足够慢,因此编译器编写者必须权衡进一步静态分析的好处,这可能使他们能够根据增加的编译时间生成更好的诊断。

The standard does not cover [2]. It allows an rvalue to be bound to a const reference, but that doesn't allow you to return a const reference and have the lifetime of the rvalue it is bound to extended as well.

And true, static analysis could catch this, but as always it's a trade-off. C++ compilation is slow enough as it is, so compiler writers have to weigh the benefits of further static analysis which might allow them to produce better diagnostics, against the increased compilation time.

清风挽心 2024-09-26 08:47:45
  1. 不,我认为标准没有提及/涵盖这个特定案例。

  2. VS 2010 给出编译警告(/Za、/W4)。

所以,这绝对是一种可以诊断的病症。

因此,我对函数进行了如下稍微调整,只是为了创建多个返回路径:

std::string const& get_phase() 
{ 
    std::string const& phase = get_env_value("PHASE"); // [1] 
    std::cout << "get_phase - " << phase << '\n'; 

    if(1){
        while(1){
            return phase;
        }
    }
    return phase;                                      // [2] 
} 

现在,VS 不会像之前那样报告警告。

例如,乍一看,编译器应该很容易检测和捕获并非所有路径都返回值。但编译器(例如VS)不会。

int get_phase() 
{
    char ch;
    if(ch){
        return 0;
    }
     // nothing returned from here.
} 

所以,我猜 OP 中的代码可能与上面所示的示例具有相同的诊断条件的复杂性,尽管我不确定。唯一的好处是标准对此案有明确的规定。

$6.6.3/2 - “从
函数的结尾相当于
无值返回;这导致
中的未定义行为
返回值函数。”

回到OP中的代码,我猜标准并没有强制这个条件成为可诊断的条件,因此编译器可以自由地做他们想做的事情。基本上可以理解,返回的引用 因此访问这样的对象将导致未定义的行为。

  1. No, I don't think Standard mentions / covers this specific case.

  2. VS 2010 gives compilation warnings (/Za, /W4).

So, definitely it looks to be a diagnosable condition.

So, I tweaked the function slightly as follows, just to create multiple return paths:

std::string const& get_phase() 
{ 
    std::string const& phase = get_env_value("PHASE"); // [1] 
    std::cout << "get_phase - " << phase << '\n'; 

    if(1){
        while(1){
            return phase;
        }
    }
    return phase;                                      // [2] 
} 

Now, VS does not report the warning as earlier.

As an example, at a first glance, it looks that it should be easy for the compiler to detect and catch that not all paths return a value. But compilers (e.g. VS) do not.

int get_phase() 
{
    char ch;
    if(ch){
        return 0;
    }
     // nothing returned from here.
} 

So, I guess the code in OP has probably the same complexities to diagnose the condition as the example shown just above, though I am not sure. The only good thing is that the Standard is clear on this case.

$6.6.3/2 - "Flowing off the
end of a function is equivalent to a
return with no value; this results in
undefined behavior in a
value-returning function."

Coming back to the code in OP, I guess the standard does not mandate this condition to be a diagnosable condition, and hence compilers are free to do as they please. It is basically understood that the returned reference points to an object which is already destructed. So accessing such an object will lead to an undefined behavior

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文