Как можно захватить отслеживание стека в C?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

80
задан Ciro Santilli 新疆改造中心法轮功六四事件 25 January 2019 в 12:18
поделиться

10 ответов

Мы использовали это для наших проектов:

https://www.codeproject.com/kb/threads/stackwalker.aspx

код немного грязен, по моему скромному мнению, но это работает хорошо. Windows только.

22
ответ дан cp.engr 24 November 2019 в 09:54
поделиться

glibc обеспечивает след () функция.

http://www.gnu.org/software/libc/manual/html_node/Backtraces.html

78
ответ дан sanxiyn 24 November 2019 в 09:54
поделиться

Поскольку Windows проверяет StackWalk64 () API (также в Windows на 32 бита). Для UNIX необходимо использовать собственный способ ОС сделать это, или нейтрализация к следу glibc (), если availabe.

Примечание однако, что взятие Stacktrace в собственном коде редко является хорошей идеей - не потому что это не возможно, но потому что Вы usally пытаетесь достигнуть неправильной вещи.

Большую часть времени люди пытаются вложить stacktrace, скажем, исключительное обстоятельство, как то, когда исключение поймано, утверждать сбои или - худший и самый неправильный из них всех - когда Вы получаете фатальное "исключение" или сигнал как нарушение сегментации.

Рассмотрение последней проблемы, большинство API потребует, чтобы Вы явно выделили память, или может сделать это внутренне. Выполнение так в уязвимом государстве, в котором Ваша программа может в настоящее время быть в, может acutally сделать вещи еще хуже. Например, отчет о катастрофическом отказе (или coredump) не отразит фактическую причину проблемы, но Вашу неудачную попытку обработать его).

я предполагаю, что Вы пробуете к achive, что вещь фатальной обработки ошибок, поскольку большинство людей, кажется, пробует это когда дело доходит до получения stacktrace. Если так, я полагался бы на отладчик (во время разработки) и разрешение процессу coredump в производстве (или мини-дамп на окнах). Вместе с надлежащим управлением символа Вы не должны испытывать никакие затруднения при расчете вскрытия инструкции по порождению.

20
ответ дан Christian.K 24 November 2019 в 09:54
поделиться

Нет никакого независимого от платформы способа сделать это.

самая близкая вещь, которую можно сделать, состоит в том, чтобы выполнить код без оптимизации. Тем путем можно присоединить к процессу (использующий отладчик Visual C++ или GDB) и получить применимое отслеживание стека.

4
ответ дан Nils Pipenbrinck 24 November 2019 в 09:54
поделиться

Для Windows, CaptureStackBackTrace() также опция, которая требует, чтобы меньше кода подготовки конца пользователя, чем StackWalk64() сделало. (Кроме того, для подобного сценария я имел, CaptureStackBackTrace() закончил тем, что работал лучше (более надежно), чем StackWalk64().)

4
ответ дан Quasidart 24 November 2019 в 09:54
поделиться

Солярис имеет команда pstack, которая была также скопирована в Linux.

2
ответ дан Peter Mortensen 24 November 2019 в 09:54
поделиться

Позвольте мне указать на Вас на свою статью. Это - только несколько строк кода.

Отладка После смерти

, Хотя у меня в настоящее время есть проблемы с x64 реализация этого .

2
ответ дан Community 24 November 2019 в 09:54
поделиться

Можно сделать это путем обхода стека назад. В действительности, тем не менее, часто легче добавить идентификатор на стек вызовов в начале каждой функции и вытолкать его в конце, тогда просто обойти ту печать содержания. Это - что-то вроде ЛАВАША, но это работает хорошо и сэкономит Вам время в конце.

-1
ответ дан Cody Brocious 24 November 2019 в 09:54
поделиться

Вы должны использовать библиотеку расслабления .

unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
unsigned long a[100];
int ctr = 0;

while (unw_step(&cursor) > 0) {
  unw_get_reg(&cursor, UNW_REG_IP, &ip);
  unw_get_reg(&cursor, UNW_REG_SP, &sp);
  if (ctr >= 10) break;
  a[ctr++] = ip;
}

Ваш подход также будет работать нормально, если вы не позвоните от общей библиотеки.

Вы можете использовать команду Addr2line в Linux, чтобы получить номер / строку / строку источника соответствующего ПК.

4
ответ дан 24 November 2019 в 09:54
поделиться

Есть backtrace () и backtrace_symbols ():

Из справочной страницы:

     #include <execinfo.h>
     #include <stdio.h>
     ...
     void* callstack[128];
     int i, frames = backtrace(callstack, 128);
     char** strs = backtrace_symbols(callstack, frames);
     for (i = 0; i < frames; ++i) {
         printf("%s\n", strs[i]);
     }
     free(strs);
     ...

Один из способов использовать это более удобным способом / ООП - сохранить результат backtrace_symbols () в конструкторе класса исключения. Таким образом, всякий раз, когда вы генерируете исключение такого типа, вы получаете трассировку стека. Затем просто предоставьте функцию для его распечатки. Например:


class MyException : public std::exception {

    char ** strs;
    MyException( const std::string & message ) {
         int i, frames = backtrace(callstack, 128);
         strs = backtrace_symbols(callstack, frames);
    }

    void printStackTrace() {
        for (i = 0; i 

...


try {
   throw MyException("Oops!");
} catch ( MyException e ) {
    e.printStackTrace();
}

Да да!

Примечание: включение флагов оптимизации может сделать итоговую трассировку стека неточной. В идеале эту возможность следует использовать с включенными флагами отладки и выключенными флагами оптимизации.

28
ответ дан 24 November 2019 в 09:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: