Perl的Carp模块是否有C等价物?

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"后跟"退出".然后它从结果中读取并按照它喜欢的方式解析它.这几乎就是我需要做的.

Leo*_*era 1

好吧,我从未尝试过显示调用堆栈,但对于我的程序,我曾经执行以下操作。

首先,我定义一个执行实际日志记录的函数。这只是一个例子;请注意,此功能非常不安全(有人缓冲区溢出吗?)

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)

好吧,没有回溯,但有些东西就是有些东西。

  • 使用 vsnprintf() 来防止缓冲区溢出。或者使用两次对 fprintf() 的调用 - 一次用于文件/函数/行信息,另一次作为 vfprintf() 来处理用户提供的格式。每个人的代码似乎都忘记打印程序名称 - argv[0]; 不过,这需要一些设置规则。 (2认同)