Я знаю, что для этого нет стандартной функции C. Мне было интересно, что это за техника для Windows и * nix? (Windows XP - это моя самая важная ОС, чтобы сделать это сейчас).Как можно захватить трассировку стека в C?
ответ
Мы использовали это для наших проектов:
https://www.codeproject.com/kb/threads/stackwalker.aspx
Код немного грязный ИМХО, но она хорошо работает. Только Windows.
Вы можете сделать это, пройдя стек назад. На самом деле, тем не менее, часто бывает проще добавить идентификатор в стек вызовов в начале каждой функции и всплывать в конце, а затем просто ходить, распечатывая содержимое. Это немного PITA, но он работает хорошо и сэкономит вам время в конце.
Не могли бы вы объяснить «ходьбу стека назад» более подробно? – Spidey 2012-08-31 20:45:55
Для этого не существует независимого от платформы способа.
Ближайшая вещь, которую вы можете сделать, - запустить код без оптимизации. Таким образом, вы можете подключиться к процессу (используя отладчик Visual C++ или GDB) и получить полезную трассировку стека.
Это не помогает мне, когда происходит сбой на встроенном компьютере в поле. :( – Kevin 2008-09-19 21:19:18
@Kevin: Даже на встроенных машинах обычно есть способ получить удаленный отладчик отладки или, по крайней мере, дамп ядра. Может быть, не раз он развернут в поле, хотя ... – ephemient 2010-01-31 06:49:37
, если вы используете gcc-glibc on ваша платформа выбора windows/linux/mac ... then backtrace() и backtrace_symbols() будут работать на всех трех платформах. Учитывая это утверждение, я бы использовал слова «нет [портативного] способа сделать это». – 2011-09-09 18:00:58
glibc обеспечивает функцию backtrace().
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
glibc FTW ... снова. (Это еще одна причина, по которой я считаю glibc абсолютным золотым стандартом, когда дело доходит до программирования на C (это и компилятор, который идет с ним). – 2011-09-09 17:53:04
Но подождите, что еще есть!Функция backtrace() предоставляет только массив указателей void *, представляющих функции вызова. «Это не очень полезно. Не бойся! glibc предоставляет функцию, которая преобразует все адреса void * (адреса функции вызова) в символы, читаемые пользователем. `char ** backtrace_symbols (void * const * buffer, int size)` – 2011-09-09 17:55:16
Я считаю void * символьным именем для функций -> IMO, который является довольно привлекательным voodoo-blackmagic. – 2011-09-09 17:55:55
Solaris имеет команду pstack, которая также была скопирована в Linux.
Для Windows проверьте API StackWalk64() (также на 32-разрядной Windows). Для UNIX вы должны использовать собственный способ ОС для этого или вернуться к backtrace glibc(), если доступно.
Обратите внимание, однако, что использование Stacktrace в родном коде редко бывает хорошей идеей - не потому, что это невозможно, а потому, что вы обычно пытаетесь достичь неправильной вещи.
В большинстве случаев люди пытаются получить стопку в, скажем, исключительное обстоятельство, например, когда исключение поймано, утверждение терпит неудачу или - худшее и самое неправильное из всех - когда вы получаете фатальное «исключение», или сигнал, как нарушение сегментации.
Учитывая последнюю проблему, большинство API-интерфейсов потребуют, чтобы вы явно выделяли память или могли делать ее внутренне. Выполнение этого в хрупком состоянии, в котором может находиться ваша программа, может резко ухудшить ситуацию. Например, отчет о сбое (или coredump) не будет отражать фактическую причину проблемы, но ваша неудачная попытка справиться с этим).
Я предполагаю, что вы пытаетесь достичь этой ошибки, поскольку большинство людей, похоже, пытается это сделать, когда дело доходит до получения stacktrace. Если это так, я буду полагаться на отладчик (во время разработки) и позволить процессу coredump в процессе производства (или мини-дампа в окнах). Вместе с надлежащим управлением символами вам не составит труда определить причину смерти.
Для Windows, CaptureStackBackTrace()
также является опцией, которая требует меньше кода подготовки на конце пользователя, чем StackWalk64()
. (Кроме того, по аналогичному сценарию у меня был CaptureStackBackTrace()
, который работал лучше (более надежно), чем StackWalk64()
.)
Могу ли я указать на свою статью. Это всего лишь несколько строк кода.
Хотя я в настоящее время есть проблемы с x64 implementation of this.
Вы должны использовать unwind library.
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, чтобы получить номер источника/номер соответствующего ПК.
Там в трассировку(), и 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);
...
Один из способов использовать это в более удобной/OOP образом, чтобы сохранить результат 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();
}
Та да!
Примечание: включение флажков оптимизации может привести к неточной результирующей трассировке стека. В идеале можно использовать эту возможность с отключением флагов отладки и флагов оптимизации.
В течение последних нескольких лет я использовал libbacktrace Яна Лэнса Тейлора. Он намного чище, чем функции библиотеки GNU C, которые требуют экспорта всех символов. Это обеспечивает большую полезность для генерации обратных трасс, чем libunwind. И последнее, но не менее важное: он не побежден ASLR, как подходы, требующие внешних инструментов, таких как addr2line
.
Libbacktrace первоначально был частью дистрибутива GCC, но в настоящее время доступны автором в виде отдельной библиотеки под лицензией BSD:
https://github.com/ianlancetaylor/libbacktrace
На момент написания, я бы не использовать ничего другого, если мне не нужно создавать обратные трассировки на платформе, которая не поддерживается libbacktrace.
- 1. Как захватить трассировку стека?
- 2. Как захватить трассировку стека для приложения Ncurses?
- 3. Можно ли отключить трассировку стека в Lua?
- 4. Как отформатировать трассировку стека Exception в C#?
- 5. Как регистрировать трассировку стека?
- 6. как захватить трассировку в gevent
- 7. Программно генерировать трассировку стека в Objective C
- 8. Как получить трассировку стека нити
- 9. Как распечатать трассировку стека StackOverflowException
- 10. Как найти эту трассировку стека?
- 11. Как распечатать трассировку стека исключений
- 12. Как консолидировать трассировку стека Springframework.beans.factory.UnsatisfiedDependencyException?
- 13. Как читать трассировку стека clojure?
- 14. Показать трассировку стека DNN?
- 15. трассировку не дает мне полную трассировку стека
- 16. Как отложить трассировку стека в python?
- 17. Получить трассировку стека в Java
- 18. Как отключить трассировку стека в node-sqlite3?
- 19. Помогите интерпретировать эту трассировку стека
- 20. Как получить полную трассировку стека в android?
- 21. Как распечатать трассировку стека в пользовательском исключении?
- 22. Как сохранить трассировку стека в этом случае?
- 23. Как вывести глубокую трассировку стека в node.js?
- 24. Как получить трассировку стека в Rails?
- 25. Как отключить трассировку стека в python
- 26. Как показать полную трассировку стека в Nodeunit?
- 27. Как показать трассировку стека в пудбе?
- 28. Как сбросить трассировку стека в linux
- 29. Как распечатать полную трассировку стека в исключении?
- 30. Как найти трассировку стека в Visual Studio?
Для ядра: http://stackoverflow.com/questions/21143924/how-to-print-the-current-thread-stack-trace-in-c, версия C/C++: http: // stackoverflow. com/questions/3899870/print-call-stack-in-c-or-c – 2015-07-02 18:37:38