Other Alias
backtrace, backtrace_symbols_fd
ОБЗОР
#include <execinfo.h>
int backtrace(void **buffer, int size);
char **backtrace_symbols(void *const *buffer, int size);
void backtrace_symbols_fd(void *const *buffer, int size, int fd);
ОПИСАНИЕ
Функция backtrace() возвращает список запущенных функций вызвавшей
программы в массив, на который указывает buffer. Список вызванных функций
(backtrace) — это последовательность в данный момент активных вызовов
функций программы. Каждый элемент в массиве, на который указывает buffer,
имеет тип void * и указывает на адрес возврата из соответствующего
стекового кадра (stack frame). В аргументе size задаётся максимальное
количество адресов, которые могут храниться в buffer. Если список
вызванных функций больше size, то возвращаются size адресов функций,
вызванных последними; чтобы получить полный список вызванных функций,
сделайте buffer и size достаточно большими.
Набор адресов, полученных от backtrace() через buffer, функция backtrace_symbols() транслирует в массив строк, в которых адреса представлены в символическом виде. В аргументе size передаётся количество адресов в buffer. Символический вид каждого адреса содержит имя функции (если его можно определить), шестнадцатеричное смещение в функции и реальный адрес возврата (в шестнадцатеричном виде). Результатом функции backtrace_symbols() является адрес массива указателей на строки. Этот массив выделяется backtrace_symbols() с помощью malloc(3) и должен освобождаться вызывающим (строки, на которые указывают указатели в массиве, освобождаться не должны).
Функция backtrace_symbols_fd() ожидает аргументы buffer и size как у backtrace_symbols(), но вместо записи строк в массив вызывающему, она записывает строки, одну в строке, в файловый дескриптор fd. Функция backtrace_symbols_fd() не вызывает malloc(3) и поэтому может применяться в случаях, когда вызов malloc(3) может завершаться ошибкой.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция backtrace() возвращает количество адресов, записанных в
buffer, и не может быть больше size. Если возвращаемое значение меньше
size, то был сохранён полный список вызванных функций; если значение
равно size, то список может быть не полным, то есть адреса самых старых
кадров стека могут отсутствовать.
При успешном выполнении backtrace_symbols() возвращает указатель на массив, выделенный malloc(3); при ошибке возвращается NULL.
ВЕРСИИ
Функции backtrace(), backtrace_symbols() и backtrace_symbols_fd() появились в glibc начиная с версии 2.1.
АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс Атрибут Значение
backtrace(),
backtrace_symbols(),
backtrace_symbols_fd()
безвредность в потоках: безвредно (MT-Safe)
СООТВЕТСТВИЕ СТАНДАРТАМ
Эти функции являются расширениями GNU.
ЗАМЕЧАНИЯ
Поведение данных функций основано на предположении, что адреса возврата из
функций хранятся в стеке. Заметим следующее:
Символьные имена могут быть недоступны, если не указаны специальные параметра компоновщика. В системах с компоновщиком GNU необходимо использовать параметр -rdynamic. Заметим, что имена «статических» функций не показываются, и недоступны в списке вызовов функций.
ПРИМЕР
Программа, представленная далее, демонстрирует использование backtrace()
и backtrace_symbols(). В следующем сеансе оболочки показано, что может
получиться при запуске программы:
$ cc -rdynamic prog.c -o prog $ ./prog 3 backtrace() returned 8 addresses ./prog(myfunc3+0x5c) [0x80487f0] ./prog [0x8048871] ./prog(myfunc+0x21) [0x8048894] ./prog(myfunc+0x1a) [0x804888d] ./prog(myfunc+0x1a) [0x804888d] ./prog(main+0x65) [0x80488fb] /lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c] ./prog [0x8048711]
Исходный код программы
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void
myfunc3(void)
{
int j, nptrs;
#define SIZE 100
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() вернула %d адресов\n", nptrs);
/* При вызове backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
получилось бы подобное следующему: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
static void /* "static" означает не экспортировать символ... */
myfunc2(void)
{
myfunc3();
}
void
myfunc(int ncalls)
{
if (ncalls > 1)
myfunc(ncalls - 1);
else
myfunc2();
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "%s количество-вызовов\n", argv[0]);
exit(EXIT_FAILURE);
}
myfunc(atoi(argv[1]));
exit(EXIT_SUCCESS);
}

