В вычислении , A трассировки стеки (также называемая стек трассировки [1] или стека отслеживающего [2] ) представляет собой отчет из активных кадров стека в определенный момент времени во время выполнения программы . Когда программа запускается, память часто динамически выделяется в двух местах; стека и кучи . Память постоянно выделяется в стеке, но не в куче, что отражает их имена. Стек также относится к программной конструкции, поэтому для отличия этот стек называется стеком времени выполнения программы.. Технически, как только блок памяти был выделен в стеке, его нелегко удалить, поскольку могут быть другие блоки памяти, которые были выделены до него. Каждый раз, когда функция вызывается в программе, блок памяти выделяется поверх стека выполнения, который называется записью активации (или указателем стека). На высоком уровне запись активации выделяет память для параметров функции и объявленных локальных переменных. в функции.
Программисты обычно используют трассировку стека во время интерактивной и посмертной отладки . Конечные пользователи могут видеть трассировку стека, отображаемую как часть сообщения об ошибке , о котором пользователь может затем сообщить программисту.
Трассировка стека позволяет отслеживать последовательность вызываемых вложенных функций - до точки, где создается трассировка стека. В посмертном сценарии это распространяется на функцию, в которой произошел сбой (но не обязательно). Вызовы одного уровня не отображаются в трассировке стека.
Языковая поддержка
Многие языки программирования, включая Java и C # , имеют встроенную поддержку для получения текущей трассировки стека с помощью системных вызовов. C ++ не имеет встроенной поддержки для этого, но пользователи C ++ могут извлекать трассировки стека с помощью (например) библиотеки stacktrace . В JavaScript , исключение держать свойство , которое содержит стек от того места , где он был брошен.stack
Python
В качестве примера следующая программа Python содержит ошибку.
def a (): я = 0 j = b ( я ) вернуть jdef b ( z ): k = 5 если z == 0 : c () вернуть k + zdef c (): ошибка ()а ()
При запуске программы в стандартном интерпретаторе Python появляется следующее сообщение об ошибке.
Traceback (самый последний вызов последнего): Файл "tb.py" , строка 15 , в <модуль> () Файл "tb.py" , линия 3 , в виде J = б ( я ) Файл "tb.py" , строка 9 , в файле b c () "tb.py" , строка 13 , в c error () NameError : имя 'error' не определено
Трассировка стека показывает, где возникает ошибка, а именно в c
функции. Это также показывает, что c
функция была вызвана пользователем b
, который был вызван пользователем a
, который, в свою очередь, был вызван кодом в строке 15 (последней строке) программы. Записи активации для каждой из этих трех функций должны быть расположены в стеке таким образом, чтобы a
функция занимала нижнюю часть стека, а c
функция - верхнюю часть стека.
Ява
В Java трассировки стека могут быть сброшены вручную с помощью Thread.dumpStack()
[3]. Введите следующие данные:
public class Main { public static void main ( String args [] ) { демо (); } static void demo () { demo1 (); } static void demo1 () { demo2 (); } static void demo2 () { demo3 (); } static void demo3 () { Резьба . dumpStack (); }}
В исключении перечислены функции в порядке убывания, поэтому наиболее внутренний вызов идет первым.
java.lang.Exception: трассировка стека в java.lang.Thread.dumpStack (Thread.java:1336) в Main.demo3 (Main.java:15) в Main.demo2 (Main.java:12) в Main.demo1 (Main.java:9) в Main.demo (Main.java:6) в Main.main (Main.java:3)
C и C ++
И C, и C ++ не имеют встроенной поддержки трассировки стека, но библиотеки, такие как glibc и boost, содержат методы, которые работают аналогично им. [4] [5]
Например, Glibc «s backtrace()
функция возвращает выходной сигнал с программной функцией и адресом памяти.
./a.out () [0x40067f]./a.out () [0x4006fe]./a.out () [0x40070a]/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f7e60738f45]./a.out () [0x400599]
Ржавчина
В Rust есть два типа ошибок. Функции, использующие макрос паники , «не подлежат восстановлению» и полностью прерывают выполнение программы. Функции, возвращающие a std::result::Result
, "восстанавливаемы" и с ними можно аккуратно обрабатывать. Однако исправимые ошибки не могут генерировать трассировку стека, поскольку они добавляются вручную, а не являются результатом ошибки времени выполнения.
По состоянию на июнь 2021 года в Rust появилась экспериментальная поддержка трассировки стека при неисправимых ошибках. Rust поддерживает печать в stderr при возникновении паники в потоке, но ее необходимо включить, установив RUST_BACKTRACE
переменную среды . [6]
Когда эта функция включена, такая обратная трассировка выглядит так, как показано ниже, с самым последним вызовом первым.
поток 'main' запаниковал на 'execute_to_panic', main.rs:3трассировка стека: 0: std :: sys :: imp :: backtrace :: tracing :: imp :: unwind_backtrace 1: std :: panicking :: default_hook :: {{closure}} 2: std :: panicking :: default_hook 3: std :: panicking :: rust_panic_with_hook 4: std :: panicking :: begin_panic 5: Futures :: task_impl :: with 6: фьючерсы :: task_impl :: park...
Смотрите также
Рекомендации
- ^ "Руководство по libc: трассировки" . gnu.org . Проверено 8 июля 2014 года .
- ^ «трассировка - распечатать или получить трассировку стека» . python.org . Проверено 8 июля 2014 года .
- ^ «Поток (Java Platform SE 8)» . docs.oracle.com . Проверено 15 июня 2021 .
- ^ «Обратные следы (Библиотека GNU C)» . www.gnu.org . Проверено 15 июня 2021 .
- ^ «Начало работы - 1.76.0» . www.boost.org . Проверено 15 июня 2021 .
- ^ "std :: backtrace - Rust" . doc.rust-lang.org . Проверено 15 июня 2021 .