2

一部の int 値が予期せずゼロになるという奇妙なバグのある複雑なプログラムがあります。

この組み込み型の値を追跡したいので、簡単にデバッグできます。

そのために、次の ValueWatcher テンプレート クラスを作成して、ValueWatcher が逆参照している場合を除いて、ほとんどの値の変更を追跡できるようにしました。(プログラムには int *, & が必要なため、これらの逆参照演算子を作成しました)

template <typename T>
class ValueWatcher
{   
public:
    ValueWatcher(const T &val)
    {
        cout << "constructor with raw value " << val << endl;

        _cur = _old = val;
    }

    ValueWatcher(const ValueWatcher& vw)    
    {
        cout << "constructor with ValueWatcher " << vw._cur << endl;

        _cur = vw._cur;
    }

    ValueWatcher& operator=(const ValueWatcher &rhs)
    {
        cout << "operator= with ValueWatcher " << rhs._cur << endl;

        _cur = rhs._cur;

        onChanged();

        return *this;
    }

    ValueWatcher& operator=(const T &val)
    {
        cout << "operator= with " << val << endl;

        _cur = val;

        onChanged();

        return *this;
    }

    int *operator&()
    {
        cout << "addressing operator" << endl;

        // can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!

        return &_cur;
    }

    operator int&()
    {
        cout << "operator int&" << endl;

        // can't track anymore!!!!!!!!!!!!!!!!!!!!!!!!!

        return _cur;
    }

    operator int&() const
    {
        cout << "const operator int&" << endl;

        return _cur;
    }

    operator int() const
    {
        cout << "operator int" << endl;

        return _cur;
    }

private:
    void onChanged()
    {
        // update old and do proper action

    }

    T _cur;
    T _old;

};

問題は、クライアント コードが ValueWatcher の int & または int * を必要とする場合、int & または int * を指定できますが、int * または & は ValueWatcher インスタンスを保持できないため、追跡できなくなります。

これを解決する方法はありますか?組み込み型の & または * を返すだけでなく、参照またはポインター クラスのインスタンスを返すことで解決できると思います。しかし、私はそれを行う方法がわかりません。

さらに、デバッガーでこのプログラムを実行できません。この問題は REAL 環境でのみ発生し、再現が非常に困難です。

4

6 に答える 6

2

デバッガーで実行したときに動作を再現できる場合は、値の変更またはメモリ変更のブレークポイントを設定できるはずです。これはおそらく、プロキシ実装を導入するよりも簡単です。

于 2010-06-20T15:08:49.773 に答える
0

変数に PAGE_SIZE バイトを確保できる場合は、VirtualProtectを使用してメモリのこの部分をロックできます (Windows を使用している場合)。たとえば、読み取り専用アクセスを設定できます。その後、その変数にアクセスしようとすると、プログラムがクラッシュします (そのため、メモリ ダンプを記述し、変数を変更するルーチンを特定することができます)。この手法を使用して、同様の問題を特定しました(マルチスレッドアプリ、何かがメモリブロックをランダムに上書きしていました)。マシンをすぐにデバッグできない場合は、MiniDumpWriteDumpを使用してダンプを書き込んでみてください。WinDBG または Visual Studio を使用してメモリ ダンプをデバッグできます。

于 2010-06-20T15:33:49.433 に答える
0

あなたが真剣に絶望しているなら:

#define int ValueWatcher<int>

より良いシナリオでは、使用します

//typedef int intt;
typedef ValueWatcher<int> intt;

次に、int を必要とするすべてのコードを書き直して置き換えます。に置き換えint*ますintt*。に置き換えint&ますintt&

于 2010-06-20T15:40:22.490 に答える
0

この問題は、デバッグしていないときにのみ発生するとおっしゃっています。そのため、あいまいで、最適化を使用してビルドする場合にのみ発生するバグがあると思います。この動作には、次の 2 つの説明が考えられます。

  • どこかに競合状態があります

  • 変数を適切に初期化しませんでした...そのため、最適化を使用してビルドすると、デバッグ時とは異なる方法で値が初期化されます。

  • 変数の1つを上書きしているバッファオーバーランがどこかにあります。繰り返しますが、これは最適化を使用してビルドした場合にのみ見られるものです...デバッグ用にビルドすると、コンパイラはスタック上の変数の周りに余分なスペースを残します...これはクッションとして機能し、いくつかのバグが明らかになるのを防ぐことができます.

これらの問題をより詳細に説明する関連する SO 投稿を次に示します。

プログラムはリリース ビルド時にのみクラッシュします -- デバッグ方法は?

于 2010-06-20T15:48:18.157 に答える
0

これはおそらく最善の解決策ではありませんが、* または & が値ウォッチャーへのポインター/参照を返す場合はどうでしょうか? それ以外の場合は、* または & の使用を禁止します。(それを実装しないか、非公開にすることによって)。

于 2010-06-20T15:08:17.527 に答える
0

これは不可能だと思います。int* または int& を返すと、何も追跡できなくなります。私が考えることができる唯一の方法 (そして正しい方法、IMO) は、デバッガーを使用し、適切な条件で監視ポイントを設定することです。条件が満たされると、デバッガーはプログラムに割り込んで停止し、メモリや呼び出しスタックなどを検査できるようにします。

于 2010-06-20T15:12:31.837 に答える