backtrace, backtrace_symbols, backtrace_symbols_fd -
поддержка
самоотладки
в
приложении
Standard C library (
libc,
-lc)
#include <execinfo.h>
int backtrace(void *buffer[.size], int size);
char **backtrace_symbols(void *const buffer[.size], int size);
void backtrace_symbols_fd(void *const buffer[.size], 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(), and
backtrace_symbols_fd() are provided since glibc 2.1.
Описание
терминов
данного
раздела
смотрите в
attributes(7).
Интерфейс |
Атрибут |
Значение |
backtrace(), backtrace_symbols(),
backtrace_symbols_fd() |
Безвредность
в нитях |
MT-Safe |
Эти
функции
являются
расширениями
GNU.
Поведение
данных
функций
основано
на
предположении,
что адреса
возврата
из функций
хранятся в
стеке.
Заметим
следующее:
- •
- Отсутствие
указателей
кадров
(происходит
при
указании
gcc(1) любого
ненулевого
уровня
оптимизации)
может
вызвать
нарушение
этих
предположений.
- •
- Встраиваемые
(inlined) функции
не имеют
стековых
кадров.
- •
- Оптимизация
хвостовых
вызовов
приводит к
замещению
одного
стекового
кадра
другим.
- •
- Функция
backtrace() и backtrace_symbols_fd() не
вызывает
malloc() явным
образом, но
они
являются
частью libgcc,
которая
загружается
динамически
при первом
использовании.
Обычно,
динамическая
загрузка
вызывает
malloc(3). Если
вам нужно,
чтобы
работа с
этими
функциями
не
приводила
к
выделению
памяти
(например,
в
обработчиках
сигналов),
то перед
обращением
загрузите
libgcc
самостоятельно.
Символьные
имена
могут быть
недоступны,
если не
указаны
специальные
параметра
компоновщика.
В системах
с
компоновщиком
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>
#define BT_BUF_SIZE 100
void
myfunc3(void)
{
int nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_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 (size_t j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
static void /* "static" means don't export the symbol... */
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);
}
addr2line(1),
gcc(1),
gdb(1),
ld(1),
dlopen(3),
malloc(3)
Русский
перевод
этой
страницы
руководства
был сделан
Artyom Kunyov <
[email protected]>, Azamat Hackimov
<
[email protected]>, Dmitriy Ovchinnikov
<
[email protected]>, Dmitry Bolkhovskikh <
[email protected]>,
ITriskTI <
[email protected]>, Yuri Kozlov <
[email protected]>
и Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]