【发布时间】:2010-12-07 21:17:04
【问题描述】:
在我用 C 完成的一些项目中,我喜欢使用以下与 Perl 的 warn 和 die 子例程类似的宏:
#include <stdio.h>
#include <stdlib.h>
#define warn(...) \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, " at %s line %d\n", __FILE__, __LINE__)
#define die(...) \
warn(__VA_ARGS__); \
exit(0xFF)
是否存在像 Perl 的来自 Carp 的鲤鱼、呱呱、咯咯和忏悔子例程?我想从用户的角度报告错误。
如果没有,我知道 glibc 中有 backtrace() 和 backtrace_symbols() 函数以及 -rdynamic gcc 选项可以为我提供函数名称和代码地址的回溯。但我想要更好的东西;可以访问调用堆栈中的文件、行和函数名,就像 Perl 的调用者子例程一样。这样我就可以编写自己的 libcarp 以在我的 c 程序中使用。
编辑:2009-10-19
我正在考虑创建一些在 basename(argv[0]) 上可用时使用 gdb 的东西,然后处理堆栈跟踪以生成我想要的不同类型的消息。它应该能够确定我是否不在可调试的可执行文件中,或者没有 gdb 的系统,在这种情况下,carp 和 cluck 将成为警告,而 craok 和承认将成为死亡。
我以前从未像这样使用过 gdb(我只在我的程序开始时运行它,而不是在它已经运行时)。但是我在 glib 中发现了一些函数(g_on_error_stack_trace 和 stack_trace),它们看起来非常接近我想要做的:它使用参数 basename(argv[0]) 和进程 id 分叉一个 gdb 进程,然后写入它的标准输入 (已被重定向到管道)命令“回溯”后跟“退出”。然后它从结果中读取并以它喜欢的方式解析它。这几乎正是我需要做的。
【问题讨论】:
-
对于那些不熟悉 Perl 的人,carp 和 croak 执行示例 warn 和 die 宏所做的事情,仅使用来自当前子调用者的文件和行。咯咯和坦白做同样的事情,只是有一个完整的堆栈跟踪。 (一些细节简化)
-
对于真正的多语句宏,强烈建议将它们包装在 do { ... } while(0) 中,以使其作为语句按预期工作。