c - 是否有与 Perl 的 Carp 模块等效的 C 语言?

标签 c perl die backtrace carp

在我用 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)

有没有像 Carp 中的 Perl 的 carp、croak、cluck 和 confess 子例程这样的东西存在? ?我想要一些东西来从用户的角度报告错误。

如果没有,我知道 glibc 中有 backtrace() 和 backtrace_symbols() 函数,它们与 -rdynamic gcc 选项一起可以为我提供函数名称和代码地址的回溯。但我想要更好的东西;可以访问调用堆栈中的文件、行和函数名称,就像 Perl 的调用者子例程一样。这样我就可以编写自己的 libcarp 用于我的 C 程序。

编辑:2009-10-19

我正在考虑创建一些在 basename(argv[0]) 上可用时使用 gdb 的东西,然后处理堆栈跟踪以生成我想要的不同类型的消息。它应该能够确定 im 是否不在可调试的可执行文件中,或者是没有 gdb 的系统,在这种情况下,carp 和 cluck 将变为 warns,而 craok 和 confess 将变为 dies。

我以前从未像这样使用过 gdb(我只是在开始时用我的程序运行它,而不是在它已经运行时)。但是我在 glib 中发现了一些函数(g_on_error_stack_trace 和 stack_trace),它们看起来非常接近我想要做的事情:它用参数 basename(argv[0]) 和进程 id 派生一个 gdb 进程,然后写入它的标准输入 (已被重定向到管道)命令“回溯”后跟“退出”。然后它从它的结果中读取并按照它喜欢的方式解析它。这几乎正​​是我需要做的。

最佳答案

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

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

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);
}

但是,这不是很实用。实用的是用宏来调用这个函数。

#define die( ... ) \
        strLog( __FILE__, __PRETTY_FUNCTION__, \
        __LINE__, __VA_ARGS__ )

然后你就可以像printf()一样调用了。

if (answer == 42) die("Oh, %d of course.", answer);

你会得到这样的东西:

main.c:10:somefunc: Oh, 42 of course.

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

关于c - 是否有与 Perl 的 Carp 模块等效的 C 语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1586709/

相关文章:

perl - 对存储在哈希中的 AoA 进行操作。 PDL 与无 PDL

perl - 如何从 Perl 中的数组中获取加权随机选择?

netlogo - 如果其中一个链接消失,如何更改海龟的属性?

jquery - 如何正确终止一个函数

c - C 中的递归斐波那契

c - 将子进程标准输出重定向到 C 中的管道

C - 将枚举用于位标志 - 警告 : enumerated type mixed with another type

c - 套接字:获取未知字符而不是 HTML 内容

arrays - Perl 中的排序

PHP:exit()、die() 和 return 之间有什么区别;在 "self"和包含的文件中?