Jak*_*ake 7 c perl carp die backtrace
在我用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)
Run Code Online (Sandbox Code Playgroud)
有没有像Perl的鲤鱼,呱呱,咯咯和鲤鱼的忏悔子程序那样存在的东西?我想从用户角度报告错误.
如果没有,我知道glibc中有backtrace()和backtrace_symbols()函数,它们与-rdynamic gcc选项一起可以为我提供函数名和代码地址的回溯.但我想要一些更好的东西; 可以访问调用堆栈中的文件,行和函数名称,如Perl的调用者子例程.我可以编写自己的libcarp用于我的c程序.
编辑:2009-10-19
我正在考虑在basename(argv [0])上创建使用gdb的东西,然后处理堆栈跟踪以生成我想要的不同类型的消息.它应该能够确定我是不是在可调试的可执行文件中,还是没有gdb的系统,在这种情况下,carp和cluck会变成警告并且Craok和confess将会死亡.
我之前从未使用过这样的gdb(我只在开始时使用我的程序运行它,而不是在它已经运行时).但我发现glib中的一些函数(g_on_error_stack_trace和stack_trace)看起来非常接近我想要做的事情:它使用参数basename(argv [0])和进程id分配gdb进程,然后写入其stdin(已被重定向到管道)命令"backtrace"后跟"退出".然后它从结果中读取并按照它喜欢的方式解析它.这几乎就是我需要做的.
好吧,我从未尝试过显示调用堆栈,但对于我的程序,我曾经执行以下操作。
首先,我定义一个执行实际日志记录的函数。这只是一个例子;请注意,此功能非常不安全(有人缓冲区溢出吗?)
void strLog(char *file, char *function, int line, char *fmt, ...)
{
char buf[1024];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
fprintf(stderr, "%s:%s:%d:%s\n", file, function, line, buf);
}
Run Code Online (Sandbox Code Playgroud)
然而,这不太实用。实用的是使用宏来调用该函数。
#define die( ... ) \
strLog( __FILE__, __PRETTY_FUNCTION__, \
__LINE__, __VA_ARGS__ )
Run Code Online (Sandbox Code Playgroud)
然后你就可以像这样调用了printf()。
if (answer == 42) die("Oh, %d of course.", answer);
Run Code Online (Sandbox Code Playgroud)
你会得到这样的结果:
main.c:10:somefunc: Oh, 42 of course.
Run Code Online (Sandbox Code Playgroud)
好吧,没有回溯,但有些东西就是有些东西。