C ++跟踪基元类型值更改

时间:2010-06-20 15:04:58

标签: c++ reference overloading dereference operator-keyword

我有一个复杂的程序,有一些奇怪的错误,一些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&amp;或者是ValueWatcher的int *,它可以给出int&amp;或者int *但是 - int *或&amp;无法保存ValueWatcher实例,因此无法再跟踪。

无论如何要解决这个问题?我认为它可以通过返回引用或指针类实例来解决,而不仅仅是返回&amp;或者* of built-int类型。但我不知道该怎么做。

另外 - 我无法使用调试器运行此程序。问题只出现在REAL环境中,很难再现。

6 个答案:

答案 0 :(得分:2)

如果您可以在调试器中运行时重现该行为,则应该能够设置值更改内存更改断点。这可能比引入代理实现更容易。

答案 1 :(得分:0)

它可能不是最好的解决方案,但如果你的*或&amp;返回指向值观察者的指针/引用?否则我会禁止使用*或&amp ;. (通过不实施或私有化)。

答案 2 :(得分:0)

我不认为这是可能的。一旦你返回int *或int&amp;,你就失去了跟踪任何东西的能力。我能想到的唯一方法(和正确的方法,IMO)是使用调试器并设置具有适当条件的观察点。满足条件时,调试器将中断并暂停程序,以便检查内存,调用堆栈等。

答案 3 :(得分:0)

如果您可以为变量节省PAGE_SIZE字节,那么您可以使用VirtualProtect锁定这部分内存(如果您在Windows上) - 例如,您可以设置只读访问权限。之后,任何试图访问该变量的东西都会使程序崩溃(因此您将能够编写内存转储和精确修改变量的例程)。我使用这种技术来查明类似的问题(多线程应用程序,某些东西随机覆盖了内存块)。如果无法立即调试计算机,请尝试使用MiniDumpWriteDump编写转储。您将能够使用WinDBG或Visual Studio调试内存转储。

答案 4 :(得分:0)

如果你非常绝望:

#define int ValueWatcher<int>

在更好的情况下,您可以使用

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

然后重新编写想要int的所有代码并替换它。将int*替换为intt*。将int&替换为intt&

答案 5 :(得分:0)

你说你只是在没有调试的时候才看到这个问题,所以我猜你有一个不明确的错误,只有在用优化构建时才能看到。这种行为有几种可能的解释:

  • 你某处有种族情况

  • 您没有正确初始化变量...所以在使用优化进行构建时,您的值的初始化方式与调试时不同。

  • 你的某个地方有一个缓冲区溢出,它正在写一个变量。再次,这可能是你在使用优化构建时才会看到的......当你为调试构建时,编译器将在堆栈上的变量周围留出额外的空间......这可以起到缓冲作用,可以防止一些错误暴露自己

这是一篇相关的SO文章,更详细地解释了这些问题:

Program only crashes as release build -- how to debug?