我有一个复杂的程序,有一些奇怪的错误,一些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环境中,很难再现。
答案 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文章,更详细地解释了这些问题: