4

私は以下のようなコードに出くわしました。スコープ内の同じ関数内で同時に同じ名前を持つ 2 つのスタック変数は有効ですが、問題が発生する可能性があります。(読んでください:これをデバッグするのに30分無駄にしました)。VS2010 の警告レベル 4 (最高レベル) では、この種のことをキャッチすることを望んでいたでしょう。何か足りないのでしょうか、それとももう一度 lint を使ってコード ベース全体にヒットする時が来ましたか? lint などの静的分析ツールは、このような名前の競合を検出するでしょうか?

   char *x = strchr(Buffer,' ');
   if (x)
   {
     *x = 0;
     x++;
     char *x = strchr(x,' ') 
     if (x)
        *x = 0;
   }
4

2 に答える 2

2

PC-Lintがこれを検出します。次のコード:

main (int argc, char *argv []) 
{
    char *x = 0;
    if (x)
    {
        char *x = 0;
    }
}

警告を出します:

main.cpp  6  Warning 578: Declaration of symbol 'x' hides symbol 'x' (line 3)
于 2013-05-16T18:41:48.793 に答える
2

編集:元の回答(以下)を書いたとき、これに気づきませんでした。投稿したコードは違法であり、未定義の動作を引き起こします。問題のある行は次のとおりです。

char *x = strchr(x,' ');

ここで、呼び出しx内のは、囲んでいるスコープで定義されたものを参照するのではなく、同じ行で以前に定義されたものを参照します。したがって、その行は初期化されていない変数から読み取るため、未定義の動作が発生します。C++ 標準から、strchrxx

§3.3.2/1 [basic.scope.pdecl]
名前の宣言 のポイントは、完全な宣言子 (第 8 節) の直後で、初期化子(存在する場合) の前です。ただし、以下に示す場合を除きます。[ 例:

   int x = 12;
   { int x = x; }

ここで、2 番目の x は独自の (不確定な) 値で初期化されます。—終わりの例]

以下の例の対応する行が次のように変更された場合、GCC は文句を言います。

int x = 21 + x; // generates "warning: x is used uninitialized in this function"

またstrchr、VS2012 で例を複製すると、次の警告が生成されます (at/W1以上):

warning C4700: uninitialized local variable 'x' used

元の答えは次のとおりです(完全に正確ではありません):

コードに違法性はありません。中括弧を追加して新しいスコープを導入しました。それらの変数名が外側のスコープで以前に定義されていたとしても、新しいスコープ内で変数を定義できます。

新しい定義の後の変数へのすべての参照は、ローカル変数の有効期間が終了するまで、外側のスコープ内の変数ではなくローカル変数を参照します。次のコードは、GCC でコンパイルした場合でも警告を生成しません。-pedantic -Wall -Wextra

#include <iostream>

int main()
{
  int x = 42;
  {
      std::cout << x << '\n';
      int x = 21;
      std::cout << x << '\n';
  }
  std::cout << x << '\n';
}

出力:

42
21
42

lint または別の静的分析ツールがそのようなものを選択するかどうかもわかりません。合法ですが、お勧めできません。

于 2013-05-16T18:17:24.610 に答える