在函数之间将文本插入C ++代码中

时间:2013-05-17 06:23:44

标签: c++ parsing lexer

我有以下要求:

  • 在任何功能的条目退出点添加文字。
  • 不是改变源代码,旁边插入(所以没有预处理器或任何东西)

例如:

void fn(param-list)
{
    ENTRY_TEXT (param-list)
    //some code
    EXIT_TEXT
}

但不仅在这么简单的情况下,它还会运行预处理器指令!

示例:

void fn(param-list)
#ifdef __WIN__
{
  ENTRY_TEXT (param-list)
  //some windows code
  EXIT_TEXT
}
#else
{
    ENTRY_TEXT (param-list)
    //some any-os code

    if (condition)
    {
        return; //should become EXIT_TEXT
    }

    EXIT_TEXT
}

所以我的问题是:有没有正确的方法呢?

我已经尝试过使用编译器使用的解析器,但由于它们都在解析之前都依赖于运行预处理器,因此对我来说没用。

一些不需要预处理器的令牌生成解析器也有些无用,因为它们生成令牌的内存映射,然后导致一个完整的新源代码,而不是只插入文本。 / p>

我正在研究的一件事是尝试使用FLEX(或JFlex),如果这是一个有效的选项,我会很感激它的一些输入。 ; - )

编辑: 澄清一点:目的是允许类似堆栈跟踪的东西。 我想跟踪每个函数调用,并且为了跟随调用层次结构,我需要在函数的入口点和函数的出口点放置一个宏。 这构建了一个函数调用跟踪。 : - )

EDIT2:编译器特定的选项不太合适,因为我们有许多不同的编译器可供使用,而且很多都没有得到任何工具的良好支持。

3 个答案:

答案 0 :(得分:3)

不幸的是,你的想法不仅不切实际(C ++解析起来很复杂),它也注定要失败。

您遇到的主要问题是异常会完全绕过您的EXIT_TEXT宏。


你有几个解决方案。

如前所述,第一种解决方案是使用平台相关的计算堆栈跟踪的方式。它可能有点不精确,特别是因为内联:即,在调用者中内联的小函数,它们不会出现在堆栈跟踪中,因为在汇编级别没有生成函数调用。另一方面,它可以广泛使用,不需要对代码进行任何手术,也不会影响性能

第二种解决方案是仅在条目上引入并使用RAII进行退出工作。比你的方案好多了,因为它会自动处理多个返回和异常,它会遇到同样的问题:如何自动执行插入 。为此,您可能希望在AST级别操作,并修改AST以引入您的小宝石。您可以使用Clang(查看c ++ 11迁移工具以查找重写的示例)或使用gcc(使用插件)来执行此操作。

最后,您还有手动注释。虽然它似乎功能不足(以及很多工作),但我要强调你不要将日志记录留给工具......我看到手动执行它有3个好处:你可以避免在性能敏感部分引入这种开销,你可以仅保留大参数的“摘要”,您可以根据当前函数的有趣内容自定义摘要。

答案 1 :(得分:1)

我建议您使用LLVM libraries & Clang开始使用。

您还可以利用C ++语言来简化您的流程。如果您只是将一个小对象插入到功能范围入口和构建的代码中。依赖于它将在退出时被销毁的事实。这应该大规模简化记录功能的“退出”。

答案 2 :(得分:0)

这并没有真正回答你的问题,但是,对于你的初始需要,你可以使用execinfo.h中的backtrace()函数(如果你使用的是GCC)。

How to generate a stacktrace when my gcc C++ app crashes