跟踪 C++ 变量值的来源
追踪C++变量值的来源出现的原因是为了更好地了解软件中发生的情况。为了实现这一目标,可以使用一种通用包装器,将感兴趣的变量包装起来,并记录每次调用时的堆栈跟踪和值。具体实现如下:
templateclass 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; } };
通过记录堆栈跟踪,可以了解软件中发生的变化情况。如果使用得当,可以在包装器中设置断点以捕获修改操作。这对于简单的情况是有效的。但是,如果涉及到序列化和其他操作,则可能需要进一步完善。可以追踪值的变化和从其他包装值构造的情况。
例如,可以通过以下示例了解追踪值的变化和构造过程:
TracingValued; 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(提问者)想要了解值背后的依赖关系图,这也有可能。从简单开始,逐步创建帮助程序以跟踪对象图和其演变可能有助于解决任何问题。想象一下更进一步的包装器,它会将某种引用记录到目标值中。但是,当然,只读取和逐步调试代码可能是解决整体问题的更好方法。《与遗留代码有效地工作》提供了一个很好的参考,可以帮助解决这个任务。
感谢你的努力。我可能会在将来使用这个方法。但我正在寻找现成的工具来追踪现有代码库中值的来源。