编译器检测返回对局部变量的引用
由于返回对局部变量的引用,我刚刚被一种令人讨厌的未定义行为所困扰。
我们知道它是邪恶的,通常编译器会打印一个漂亮的警告来告诉我们……不过,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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该标准不涵盖
[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.
不,我认为标准没有提及/涵盖这个特定案例。
VS 2010 给出编译警告(/Za、/W4)。
所以,这绝对是一种可以诊断的病症。
因此,我对函数进行了如下稍微调整,只是为了创建多个返回路径:
现在,VS 不会像之前那样报告警告。
例如,乍一看,编译器应该很容易检测和捕获并非所有路径都返回值。但编译器(例如VS)不会。
所以,我猜 OP 中的代码可能与上面所示的示例具有相同的诊断条件的复杂性,尽管我不确定。唯一的好处是标准对此案有明确的规定。
回到OP中的代码,我猜标准并没有强制这个条件成为可诊断的条件,因此编译器可以自由地做他们想做的事情。基本上可以理解,返回的引用 因此访问这样的对象将导致未定义的行为。
No, I don't think Standard mentions / covers this specific case.
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:
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.
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.
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