首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl的Carp模块是否有C等价物?

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

Stack Overflow用户
提问于 2009-10-19 02:26:51
回答 4查看 496关注 0票数 7

在我用C语言完成的一些项目中,我喜欢使用下面的宏,它们的工作原理类似于Perl的warn和dey子例程:

代码语言:javascript
复制
#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和convene子例程?我想从用户的角度来报告一些错误。

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

编辑: 2009-10-19

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

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

EN

回答 4

Stack Overflow用户

发布于 2009-10-19 12:37:11

好吧,我从来没有尝试过展示调用堆栈,但是对于我的程序,我曾经做过以下事情。

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

代码语言:javascript
复制
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);
}

然而,这并不是很实际。实用的做法是使用宏调用此函数。

代码语言:javascript
复制
#define die( ... ) \
        strLog( __FILE__, __PRETTY_FUNCTION__, \
        __LINE__, __VA_ARGS__ )

然后你就可以像printf()一样打电话了。

代码语言:javascript
复制
if (answer == 42) die("Oh, %d of course.", answer);

你会得到这样的结果:

代码语言:javascript
复制
main.c:10:somefunc: Oh, 42 of course.

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

票数 1
EN

Stack Overflow用户

发布于 2009-10-19 15:08:38

,但是我想要一些更好的东西,能够访问调用堆栈中的文件名、行名和函数名,比如Perl的调用子例程。

问题是,这需要程序员的帮助来决定您的库代码和“调用者”子例程之间的边界出现在哪里。Perl使用一些魔法(也称为启发式)来实现这一点;也许您可以使用回溯函数来做同样的事情。但总的来说,这并不是微不足道的。

票数 1
EN

Stack Overflow用户

发布于 2009-10-26 05:50:51

似乎没有什么比在C程序中使用的Carp模块更好的了,所以我在github上写了一个小库来做这件事。

该库定义了以下导出以供使用:

代码语言:javascript
复制
warn, die
carp, croak
cluck, confess

我已经添加了之前的e变体,用于在警告中添加errno字符串,因为我认为这会很有用:

代码语言:javascript
复制
ewarn, edie
ecarp, ecroak
ecluck, econfess

例如,如果您正在编写一个库,并且想要对一个问题吹毛求疵,那么只需使用

代码语言:javascript
复制
carp("%d is not a Fibonacci number!", 54);

它将显示调用您的库的第一个函数的文件和行号。

Perl的Carp模块使用不同的包而不是文件来查找可疑的子例程。它还递归地使用@ISA数组或@CARP_NOT来确定哪个子例程在受信任的程序包组之外。我打算添加一些类似的东西。如果堆栈跟踪的顶部在受信任的作用域内,则carp恢复为cluck (显示问题的完整堆栈跟踪),就像这个库所做的那样。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1586709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档