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

时间:2010-09-15 12:18:35

标签: c++ gcc-warning

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

我们知道它是邪恶的,通常编译器打印一个很好的warning来告诉我们......好吧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]并不安全,但我猜想它会变得很丑陋......

2 个答案:

答案 0 :(得分:5)

该标准未涵盖[2]。它允许rvalue绑定到const引用,但是这不允许你返回一个const引用,并且它具有被绑定的rvalue的生命周期。

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

答案 1 :(得分:2)

  1. 不,我不认为标准提及/涵盖了这个具体案例。

  2. VS 2010提供编译警告(/ Za,/ W4)。

  3. 所以,它看起来确实是一种可以诊断的疾病。

    所以,我稍微调整了这个函数,只是为了创建多个返回路径:

    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 - “流了下来   函数的结尾相当于a   没有价值的回报;这导致了   一个未定义的行为   价值回归功能。“

    回到OP中的代码,我想标准并没有强制要求这个条件成为可诊断的条件,因此编译器可以随心所欲地做。基本上可以理解,返回的参考指向已经被破坏的对象。因此,访问此类对象将导致未定义的行为