Существует ли эквивалент C для Perl-модуля 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)

Существует ли что-либо, например, карп, хрипотца, треск и перфом в Perl? Я хотел бы что-то сообщить об ошибках с точки зрения пользователей.

Если нет, я знаю, что в glibc есть функции backtrace() и backtrace_symbols(), которые вместе с опцией -rdynamic gcc могут предоставить мне обратную трассировку имен функций и кодовых адресов. Но я хочу что-то немного лучше; с доступом к именам файлов, строк и функций в стеке вызовов, как в подпрограмме вызывающего Perl. с этим я смогу написать свой собственный libcarp для использования в моих программах на c.

РЕДАКТИРОВАТЬ: 2009-10-19

Я имею в виду создание чего-то, что использует gdb, когда доступно по базовому имени (argv[0]), а затем обрабатывает трассировку стека для создания различных типов сообщений, которые я хочу. Он должен быть в состоянии определить, находится ли я в отлаживаемом исполняемом файле или в системе без gdb, и в этом случае carp и cluck станут предупреждениями, а взломы и признания - умрут.

Я никогда не использовал GDB, как это раньше (я только запускаю его с моей программой в начале, а не тогда, когда она уже работает). Но я нашел несколько функций в glib (g_on_error_stack_trace и stack_trace), которые выглядят очень близко к тому, что я хочу сделать: он разветвляет процесс gdb с аргументами basename(argv[0]) и идентификатором процесса, а затем записывает в его stdin (который был перенаправлен на канал) команда "backtrace", а затем "выход". Затем он читает из своего результата и анализирует его так, как ему нравится. Это почти то, что мне нужно сделать.

4 ответа

Но я хочу что-то немного лучше с доступом к именам файлов, строк и функций в стеке вызовов, как подпрограмма вызывающего Perl.

Проблема в том, что для этого требуется помощь программиста, чтобы решить, где появляется граница между кодом вашей библиотеки и подпрограммой "вызывающий". Perl использует некоторую магию (или эвристику), чтобы сделать это; может быть, вы могли бы сделать то же самое с функциями возврата. Но это не тривиально, в общем.

Ну, я никогда не пытался показать стек вызовов, но для своих программ я делал следующее.

Сначала я определяю функцию, которая выполняет фактическую регистрацию. Это всего лишь пример; обратите внимание, что эта функция крайне небезопасна (кто-нибудь переполняет буфер?)

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.

Ну, нет следа, но что-то есть что-то.

Похоже, что не существует ничего подобного модулю Carp для использования в программах на C, поэтому я написал небольшую библиотеку для этого на github.

Библиотека имеет следующие экспорты, определенные для использования:

warn, die
carp, croak
cluck, confess

и я добавил электронные варианты предыдущих для добавления строк errno к предупреждению, так как я думал, что это будет полезно:

ewarn, edie
ecarp, ecroak
ecluck, econfess

Например, если вы пишете библиотеку и хотите придраться к проблеме, просто используйте

carp("%d is not a Fibonacci number!", 54);

И он покажет файл и номер строки первой функции, вызывающей вашу библиотеку.

Модуль Carl в Perl использует другой пакет вместо файла для поиска подозрительной подпрограммы. Он также использует массив @ISA или рекурсивно @CARP_NOT, чтобы определить, какая подпрограмма находится вне доверенной группы пакетов. Я намерен добавить что-то похожее на это. Если вершина трассировки стека находится в пределах доверенной области действия, то карп возвращается к значению (которое показывает полную трассировку стека проблемы), как это сделает эта библиотека.

Я написал подпрограмму обратного отслеживания для моих встроенных приложений C (gcc). Он использует информацию -gstabs, если она доступна, для поиска имен функций. Одно предостережение в том, что файл elf должен быть где-то, где программа может его найти, чтобы посмотреть в сегменте stabs. В моих встроенных приложениях эльфийский файл находится во флэш-памяти, и у меня есть указатель на него. В вашем случае вам придется написать код, чтобы прочитать его с диска.

Я почти уверен, что файл и номер строки также находятся в сегменте колов.

Похоже ли это на то, что может вам помочь?

Другие вопросы по тегам