backtrace(3)

ИМЯ
backtrace, backtrace_symbols, backtrace_symbols_fd - поддержка самоотладки в приложении

LIBRARY
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 <artkun@guitarplayer.ru>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy Ovchinnikov <dmitriyxt5@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, ITriskTI <ITriskTI@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 (https://www.gnu.org/licenses/gpl-3.0.html) или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.