5

ローカル変数への参照を返すため、厄介な未定義の動作に噛まれたところです。

私たちはそれが悪であることを知っています、そして一般的にコンパイラは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]急速に醜くなる可能性があると思います...

4

2 に答える 2

5

標準はカバーしていません[2]。これにより、右辺値をconst参照にバインドできますが、const参照を返したり、バインドされている右辺値の有効期間を延長したりすることはできません。

そして確かに、静的分析はこれを捕らえることができますが、いつものようにそれはトレードオフです。C ++のコンパイルはそのままでも十分に遅いため、コンパイラの作成者は、コンパイル時間の増加に対して、より優れた診断を生成できる可能性のあるさらなる静的分析の利点を比較検討する必要があります。

于 2010-09-15T12:44:04.177 に答える
2
  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のコードに戻ると、標準ではこの条件が診断可能な条件であることが義務付けられていないため、コンパイラーは自由に実行できます。基本的に、返される参照は、すでに破棄されているオブジェクトを指していると理解されています。したがって、そのようなオブジェクトにアクセスすると、未定義の動作が発生します

于 2010-09-15T13:05:15.347 に答える