65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 代码点跟踪

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (5投票s)

2013年12月19日

CPOL

2分钟阅读

viewsIcon

20393

downloadIcon

163

一种临时解决方案,用于标记和跟踪 C++ 中的代码点

引言

虽然不应该出现这种情况,但有时很难确定程序执行过程中运行了哪些代码点。 市面上有很多专业的工具,从静态分析到仪器测量,可以回答这些问题,但在某些情况下,临时解决方案可能更有效。

背景

实现此方法是利用静态变量在程序启动前的初始化,但由于所有代码点都在函数中,因此“静态锚点”必须以某种方式放置在那里,因此需要克服 C++ 的 函数级静态变量延迟初始化 特性。

这可以通过模板类 (X) 添加一个间接引用,并带有 static 成员变量 (progloc_) 来强制每个模板参数的初始化,而该模板参数又是一个包装 struct ,用于传输所需的信息 (_FILE._ “在第” _.LINE._ 行)。

将这些组合在一起,实现此目标的最重要代码可能如下所示

template <class T> class X {
public:
    static T progloc_;
};
template <class T> T X<T>::progloc_;

#define TRACE_CODE_POINT { \
    struct ProgLocation { \
    public: \
        std::string loc_; \
        ProgLocation() : loc_(std::string(__FILE__ " at line " S__LINE__)) \
        { \
            TestFw::CodePoints::Test::imHere(loc_); \
        } \
    }; \
    TestFw::CodePoints::X<ProgLocation>  dummy; \
    TestFw::CodePoints::Test::iGotCalled(dummy.progloc_.loc_); }

ProgLocation - 构造函数中使用的 S_._LINE_._ 技巧来自 Stack Overflow 上的这里

#define S(x) #x
#define S_(x) S(x)
#define S__LINE__ S_(__LINE__)

要跟踪,可以使用以下方法

class Test
{
private:
    typedef std::set<std::string> TFuncs;
    static TFuncs registeredFunctions;
    static TFuncs calledFunctions;
public:
    static int imHere(const std::string fileAndLine)
    {
        assert(registeredFunctions.find(fileAndLine) == registeredFunctions.end());
        registeredFunctions.insert(fileAndLine);
        return 0;
    }
    static void iGotCalled(const std::string fileAndLine)
    {
        if (calledFunctions.find(fileAndLine) == calledFunctions.end())
            calledFunctions.insert(fileAndLine);
    }
    static void report()
    {
        for (TFuncs::const_iterator rfIt = registeredFunctions.begin(); 
            rfIt != registeredFunctions.end(); ++rfIt)
            if (calledFunctions.find(*rfIt) == calledFunctions.end())
                std::cout << (*rfIt) << " didn't get called" << std::endl;
    }
};

Using the Code

跟踪代码点所需的全部内容是在所需位置放置宏

TRACE_CODE_POINT  

并在程序结束时调用 Test 类的 report() 方法。

关注点

提供的解决方案由于多种原因非常 危险,应谨慎使用。 未考虑性能或线程安全性。 到目前为止,该代码仅在 MSVC 2010 和 2013 上进行了测试。

如果您打算使用该代码,您可能还需要考虑向报告方法添加一些分派。 在提示开始时提供的 zip 文件中的示例源代码包含一个这样的报告器,以及一个控制台和一个调试输出窗口接收器,还有一个方便的助手来构建主函数。

历史

  • 2013/12/20:首次发布
© . All rights reserved.