backtrace(3)

НАИМЕНОВАНИЕ
backtrace, backtrace_symbols, backtrace_symbols_fd - поддержка самоотладки в приложении

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

ОБЗОР
#include <execinfo.h>

int backtrace(int size;
              void *buffer[size], int size);

char **backtrace_symbols(int size;
              void *const buffer[size], int size);
void backtrace_symbols_fd(int size;
              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() returns the number of addresses returned in buffer, which is not greater than size. If the return value is less than size, then the full backtrace was stored; if it is equal to size, then it may have been truncated, in which case, the addresses of the oldest stack frames are not returned.

При успешном выполнении backtrace_symbols() возвращает указатель на массив, выделенный malloc(3); при ошибке возвращается NULL.

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
backtrace(), backtrace_symbols(), backtrace_symbols_fd() | Безвредность в нитях | MT-Safe

СТАНДАРТЫ
GNU.

ИСТОРИЯ
glibc 2.1.

ПРИМЕЧАНИЯ
Поведение данных функций основано на предположении, что адреса возврата из функций хранятся в стеке. Заметим следующее:

•   Отсутствие указателей кадров (происходит при указании 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() returned %d addresses\n", nptrs);

        /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
           would produce similar output to the following: */

        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 num-calls\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 (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).