Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;跟踪原语类型值更改_C++_Reference_Overloading_Dereference_Operator Keyword - Fatal编程技术网

C++ C++;跟踪原语类型值更改

C++ C++;跟踪原语类型值更改,c++,reference,overloading,dereference,operator-keyword,C++,Reference,Overloading,Dereference,Operator Keyword,我有一个复杂的程序,有一个奇怪的bug,一些int值意外地降到了零 所以我想跟踪这个内置类型值,这样我就可以很容易地调试了 为此,我创建了以下ValueWatcher模板类,以便跟踪几乎所有的值更改,ValueWatcher取消引用时除外。(我之所以使用这些解引用运算符,是因为程序需要int*,&) 模板 阶级价值观 { 公众: 估价师(const T&val) { cout这可能不是最好的解决方案,但是如果你的*or&返回一个指向你的值观察者的指针/引用呢?否则我将禁止使用*or&(通过

我有一个复杂的程序,有一个奇怪的bug,一些int值意外地降到了零

所以我想跟踪这个内置类型值,这样我就可以很容易地调试了

为此,我创建了以下ValueWatcher模板类,以便跟踪几乎所有的值更改,ValueWatcher取消引用时除外。(我之所以使用这些解引用运算符,是因为程序需要int*,&)

模板
阶级价值观
{   
公众:
估价师(const T&val)
{

cout这可能不是最好的解决方案,但是如果你的*or&返回一个指向你的值观察者的指针/引用呢?否则我将禁止使用*or&(通过不实现它或使它私有化).

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

我认为这是不可能的。一旦返回int*或int&,您就失去了跟踪任何内容的能力。唯一的方法是(国际海事组织,正确的方法)我能想到的方法是使用调试器并设置一个带有适当条件的观察点。当条件满足时,调试器将中断并停止程序,以便您可以检查内存、调用堆栈等。

如果您可以为变量留出一个页面大小的字节,那么您可以使用(如果您在windows上)-例如,您可以设置只读访问。此后,任何试图访问该变量的操作都会使程序崩溃(这样您就可以编写内存转储并查明更改该变量的例程)。我使用此技术来查明类似的问题(多线程应用程序,某些内容正在随机覆盖内存块)。如果您无法立即调试计算机,请尝试使用编写转储。您将能够使用WinDBG或Visual Studio调试内存转储。

如果您非常绝望:

#define int ValueWatcher<int>
#定义int ValueWatcher
在更好的情况下,您应该使用

//typedef int intt;
typedef ValueWatcher<int> intt;
//typedef int int;
类型DEF ValueWatcher intt;

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

你说你只在不调试时看到这个问题,所以我猜你有一个模糊的bug,只有在使用优化构建时才能看到。有两个问题对此行为的可能解释:

  • 你在什么地方有比赛条件

  • 您没有正确初始化变量…因此,在使用优化构建时,您的值的初始化方式与调试时不同

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

以下是一篇相关的SO帖子,详细解释了这些问题:


也许带条件断点的调试器会是更好的解决方案?无法使用调试器运行此程序。问题发生在真实环境中,很难再现。感谢您的回复。程序在windows上运行,但我不能使用此技术。问题是由一些逻辑错误引起的,不是随机写入内存。还可以写入这个值应该是允许的。@ljh131:在这种情况下,我只能考虑硬件断点。不过,您仍然需要某种调试器。那么,我应该更改所有相关的代码。程序代码非常庞大,所以我正在考虑另一种解决方法。不幸的是,无法使用调试器或其他东西,因为程序是在真实环境下运行的然后,你需要像以前那样包装该值,但停止返回对基础变量的访问。你需要代理中的每个请求。当然,如果问题如此微妙,这个更改可能会使它消失。另一个黑客解决方案可能是生成一个线程,定期检查内存位置的值,然后您看到了问题所在。但这就引出了一个问题,即当您在运行时检测到此错误时,您将怎么做。您可能需要检查程序及其内存内容,以了解问题存在的原因。再想一想,您可能最好只在关键区域添加日志记录。这样您就可以添加必要的debug信息,以便您可以在问题发生后尝试解决问题。或者,如果您能够在事后检测到问题,您可以添加断言以确保问题没有发生。如果问题发生,您可以使程序退出,并将其内存内容转储到可供检查的转储/核心文件中。感谢您的长回复。ju就像你说的,如果没有办法轻松找到问题,我应该修改更多的代码。感谢你的回答,但我的意思是不能用调试器调试或跟踪,因为这个bug很难复制给我。找到这个bug的唯一方法是使用这些技术并真实地看到(许多用户)条件。而且它似乎不是由内存覆盖引起的。你确定吗?你描述的症状听起来与上面列出的情况完全一样。类型不重要。变量只声明了一次。但我的问题是——正如我所提到的——当用*或&去引用时无法再跟踪。这就是为什么你需要替换int*和int&witValueWatcher*和ValueWatcher&.ahhh..我理解。这似乎是在这种情况下唯一的解决办法。
//typedef int intt;
typedef ValueWatcher<int> intt;