跟踪 C++ 变量值的来源

5 浏览
0 Comments

跟踪 C++ 变量值的来源

在某些情况下,应用程序的输出不再有效。一些输出值是错误的。用于计算这些输出的值是正确的,但在复杂的处理过程中某个时刻出现了错误。

有没有一种工具可以追踪C++变量值的来源?我以前使用过valgrind来跟踪NULL值,但我想要的是更通用的工具。

是否有一种更通用的工具可以显示导致变量在某个时间点上具有特定值的赋值链(或树)?

注:代码像几乎所有的遗留代码一样难以理解,没有单元测试等。

编辑:在变量上设置数据断点只会显示链中的终点。希望能有更多的信息。

0
0 Comments

追踪C++变量值的来源出现的原因是为了更好地了解软件中发生的情况。为了实现这一目标,可以使用一种通用包装器,将感兴趣的变量包装起来,并记录每次调用时的堆栈跟踪和值。具体实现如下:

template 
class TracingValue
{
private:
 T m_Val;
 ...    
 void LogStackTrace() {...}
public:
 // 写入操作
 TracingValue& operator= (const T& val) {
    LogStackTrace();
    m_Val=val;
    return *this;
 }
 // 读取操作     
 operator T () const { return m_Val; }
 // "连接"到其他值
 TracingValue& operator=(const TracingValue &other) {
   LogStackTrace();
   m_Val = other.m_Val;
   std::cout << "id: " << this->Id() << " new value: " << m_Val
             << " from id: " << other.Id() << std::endl;
   return *this;
 }
};

通过记录堆栈跟踪,可以了解软件中发生的变化情况。如果使用得当,可以在包装器中设置断点以捕获修改操作。这对于简单的情况是有效的。但是,如果涉及到序列化和其他操作,则可能需要进一步完善。可以追踪值的变化和从其他包装值构造的情况。

例如,可以通过以下示例了解追踪值的变化和构造过程:

TracingValue d;
d = 3.;
d = 42.;
double x = d - 2.;
std::cout << x << std::endl;
TracingValue other_d(d);
TracingValue another_d;
another_d = other_d;  

输出结果如下:

id: 1 constructed with value: 0
id: 1 new value: 3
id: 1 new value: 42
40
id: 2 constructed with value: 42
id: 2 constructed from id: 1
id: 3 constructed with value: 0
id: 3 new value: 42 from id: 2

有人可能会认为OP(提问者)想要了解值背后的依赖关系图,这也有可能。从简单开始,逐步创建帮助程序以跟踪对象图和其演变可能有助于解决任何问题。想象一下更进一步的包装器,它会将某种引用记录到目标值中。但是,当然,只读取和逐步调试代码可能是解决整体问题的更好方法。《与遗留代码有效地工作》提供了一个很好的参考,可以帮助解决这个任务。

感谢你的努力。我可能会在将来使用这个方法。但我正在寻找现成的工具来追踪现有代码库中值的来源。

0