C ++ Отслеживание изменения значения примитивного типа - PullRequest
2 голосов
/ 20 июня 2010

У меня есть сложная программа со странной ошибкой, что некоторое значение 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;

};

проблема в том, что когда клиентский код хочет int & или int * для ValueWatcher, он может в любом случае дать int & или int *но - int * или & не может содержать экземпляр ValueWatcher, поэтому не может больше отслеживать.

Есть ли способ решить эту проблему?Я думаю, что это можно решить, возвращая ссылку или экземпляр класса указателя, а не просто возвращая & или * встроенного типа.но я не знаю, как это сделать.

Кроме того, я не могу запустить эту программу с отладчиком.проблема возникает только в РЕАЛЬНОЙ среде и очень трудно воспроизвести.

Ответы [ 6 ]

2 голосов
/ 20 июня 2010

Если вы можете воспроизвести поведение при работе в отладчике, вы сможете установить изменение значения или изменение памяти точка останова.Это, вероятно, проще, чем введение прокси-реализации.

0 голосов
/ 20 июня 2010

Вы говорите, что видите эту проблему только тогда, когда не отлаживаете, поэтому я предполагаю, что у вас есть ошибка, которая неясна и может быть замечена только при сборке с оптимизацией. Есть несколько возможных объяснений этого поведения:

  • У вас где-то есть состояние гонки

  • Вы неправильно инициализировали переменную ... поэтому при построении с оптимизацией ваши значения инициализируются иначе, чем при отладке.

  • У вас где-то переполнен буфер, который записывает одну из ваших переменных. Опять же, это может быть то, что вы видите только при сборке с оптимизацией ... Когда вы собираете для отладки, компилятор оставит дополнительное пространство вокруг переменных в стеке ... что действует как амортизатор и может не дать некоторым ошибкам раскрыть себя .

Вот соответствующий пост SO, который более подробно объясняет эти проблемы:

Сбой программы только при сборке релиза - как отлаживать?

0 голосов
/ 20 июня 2010

Если вы серьезно отчаялись:

#define int ValueWatcher<int>

В лучшем случае вы бы использовали

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

Затем переписали бы весь код, который хочет получить int, и заменитеЭто.Заменить int* на intt*.Заменить int& на intt&.

0 голосов
/ 20 июня 2010

Если вы можете сэкономить байты PAGE_SIZE для своей переменной, то вы можете заблокировать эту часть памяти, используя VirtualProtect (если вы находитесь в Windows) - например, вы можете установить доступ только для чтения.После этого все, что пытается получить доступ к этой переменной, приведет к сбою программы (так что вы сможете записать дамп памяти и определить процедуру, которая изменяет переменную).Я использовал эту технику, чтобы точно определить схожую проблему (многопоточное приложение, что-то случайно перезаписывало блоки памяти).Если вы не можете отладить компьютер сразу, попробуйте записать дамп с помощью MiniDumpWriteDump .Вы сможете отлаживать дампы памяти с помощью WinDBG или Visual Studio.

0 голосов
/ 20 июня 2010

Я не думаю, что это возможно. Когда вы возвращаете int * или int &, вы теряете возможность отслеживать что-либо. Единственный способ (и правильный способ, IMO) сделать это, о котором я могу думать, это использовать отладчик и установить точку наблюдения с соответствующим условием. Когда условие выполнено, отладчик прерывает и останавливает программу, чтобы вы могли проверить память, стек вызовов и т. Д.

0 голосов
/ 20 июня 2010

Это, вероятно, не лучшее решение, но что если ваш * или & вернет указатель / ссылку на ваш наблюдатель значения? В противном случае я бы запретил использование * или &. (Не осуществляя его или не делая его частным).

...