比方说我有
foo () {
bar ();
}
其中 foo
位于 f.c
, bar
位于 b.c
,即 b.h
包含在 f.c
中 . 我想修改 bar
以打印它从调用它的任何函数 foo
调用,如下所示:
bar () {
printf ("Called from line %d in file %s",?,?);
/* Run as usual */
}
我想从predefined GCC preprocessor macros __LINE__
和 __FILE__
获取这两条信息 . 但是,如果只是插入 printf
,这些显然会分别评估 b.c
中 printf
的行和 b.c
的路径 .
我可以以某种方式将 __LINE__
和 __FILE__
的值从调用上下文传播到 bar
中的 printf
,因此会打印"Called from line x in file foo.c"吗?
我试图将 bar
重命名为 bar2
,然后在头文件_1008217中定义委托函数:
bar () {
printf ("Called from line %d in file %s",__LINE__,__FILE__);
bar2 ();
}
我们的想法是 #include
指令会将 Headers 代码复制到源文件 f.c
中,然后分别将路径替换为 f.c
和行号 . 但是,这给了我不同翻译单元的重复定义错误 .
接下来,我尝试将 static
修饰符添加到 bar2
的标头定义中,以允许多个定义 . 然后我可以编译没有错误并运行程序,但仍然只打印 bar.h
.
我哪里错了?我确信有更优雅的方式来做到这一点 .
问题:
-
为什么不使用像GDB这样的调试器?这是内核代码 .
-
为什么不进行来电方调试?大代码库 .
编辑:
为什么这不起作用?
#ifdef DEBUG_PALLOC
#define palloc_get_page(FLAGS) (palloc_get_page_debug (FLAGS, __FILE__,__LINE__))
#else
void *palloc_get_page (enum palloc_flags);
#endif
1 回答
你可以创建一个委托,但不是
.h
中的一个函数,因为__FILE__
和__LINE__
将在.h
中(并且static
修饰符在这里没有帮助),但是有一个宏将在适当的位置展开并带有正确的文件&行信息和
bar
应该接受文件和行参数:gdb方法更复杂 . 这可能适用于:
一个gdb脚本,用于打印当前断点位置/回溯并继续,
一个触发断点的协作
bar
函数(在intel / Windows上:使用Breakpoint
函数或asm("int $3")
指令,如果设置了一个标志/ env.var告诉调试器已启用,但如果经常调用bar
,这可能会减慢该计划很多)注意:如果要使其可激活或不激活,则会变得更加复杂,但通过设置命令行
-DDEBUG
标志,您可以进行以下打印:档案
bar.h
:档案
bar.c
从主程序中调用
bar2
. 如果设置了DEBUG
,bar2
是一个调用bar
的宏 . 如果未设置DEBUG
,则bar2
直接是您的功能 .请注意,除非您使用脚本生成这些模式,否则对所有函数执行此操作非常繁琐 .