我有以下要求:
例如:
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:编译器特定的选项不太合适,因为我们有许多不同的编译器可供使用,而且很多都没有得到任何工具的良好支持。
答案 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)。