2

私は、バグの原因を再現して見つけるのに大きな問題を抱えていました。発生は完全にランダムに見えるので、初期化されていない変数がどこかにあると思われます。しかし、その後、次のコードを見つけました。

CMyClass obj; // A
obj.DoStuff();

if ( somebool )
{
    CMyClass obj; // B
    obj.DoStuff();
}

obj.DoOtherStuff();

DoOtherStuff() が「B」で実行されるか、B.DoStuff() が実際に A で動作する場合があるようです。つまり、最初の obj で DoStuff() が実際に呼び出されます。

これは起こりえますか?コンパイラの警告は出なかったと思います (助けになることを期待して、コードを修正しました)。実際のコードのこの部分が、私が見つけようとしているバグの場所である可能性が非常に高いようですが、もちろん、まだ発見していない他の理由がある可能性もあります。

4

6 に答える 6

5

コードは、書かれているとおりに動作するはずです。への最初の呼び出しと へDoStuff()の最後の呼び出しは、 にDoOtherStuff()のみ送信できAます。

DoStuff()ブロック内のへの呼び出しは、 にif(somebool) { }のみ送信できBます。

標準から:

3.3.2 ローカルスコープ

  1. ブロック (6.3) で宣言された名前は、そのブロックに対してローカルです。その潜在的なスコープは、宣言のポイント (3.3.1) で始まり、宣言領域の終わりで終わります。

と:

3.3.7 名前の隠蔽

  1. 名前は、ネストされた宣言領域または派生クラス (10.2) で同じ名前を明示的に宣言することによって非表示にすることができます。

そうは言っても、おそらくこれはそのコードの作成者が意図したものではありません。変数が同じ名前の場合、その変数のインスタンスを 1 つだけ持つことが意図されている可能性がBあり、ループ内で作成されたインスタンスは誤りです。2 番目のインスタンスが意味をなすかどうかを確認するロジックを調べましたか?

于 2009-05-16T17:37:02.057 に答える
3

一部のグローバル オブジェクトに変更を加えない限りobj.DoStuff()、Valentin が指摘するように、すべてが if ステートメントのスコープ内に含まれている必要があります。

于 2009-05-16T17:38:35.203 に答える
2

グローバル変数と同じ名前のローカル変数は、そのブロック内のグローバル変数を隠します。ただし、グローバル スコープ演算子 (::) を使用して、グローバル バージョンを意味することをコンパイラに伝えることができます。

CMyClass obj; // A
obj.DoStuff();
if ( somebool )
{ 
 CMyClass obj; // B  
 obj.DoStuff();  //does on B
 ::obj.DoStuff(); //does on A
}
obj.DoOtherStuff(); //this will call A because B is destroyed

したがって、ローカル変数 B は、スコープ外になると破棄されます。グローバル変数と同じ名前のローカル変数を持つことは、通常、トラブルの原因となるため、可能な限り避けるようにしてください。

于 2009-05-16T17:38:38.823 に答える
1

いいえ、それはありえません。

コンパイラは、if スコープを終了するときに B オブジェクトが適切に破棄され、生きている間は独自のアドレス空間で動作することを保証します。

エラーは別の場所にあります。

于 2009-05-16T17:35:25.570 に答える
0

あなたのコードは構文的に正しいかもしれませんが、メソッドは何をしますか?スタックオーバーフローは、たとえば、あなたが観察しているような不気味な振る舞いを引き起こす可能性があります。

于 2009-05-16T18:52:38.020 に答える