Jump to content

Трассировка стека

В вычислительной технике трассировка стека (также называемая трассировкой стека) [1] или обратная трассировка стека [2] ) — это отчет об активных кадрах стека в определенный момент времени во время выполнения программы . При запуске программы память часто динамически распределяется в двух местах: в стеке и в куче . Память постоянно выделяется в стеке, а не в куче, что отражает их имена. Стек также относится к программной конструкции, поэтому, чтобы отличить его, этот стек называется стеком вызовов функций программы . Технически, как только блок памяти был выделен в стеке, его невозможно легко удалить, поскольку до него могут быть выделены другие блоки памяти. блок памяти, называемый записью активации Каждый раз, когда в программе вызывается функция, поверх стека вызовов выделяется . Обычно запись активации хранит аргументы функции и локальные переменные. Что именно он содержит и как он расположен, определяется соглашением о вызовах .

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

Трассировка стека позволяет отслеживать последовательность вызываемых вложенных функций до момента создания трассировки стека. В посмертном сценарии это распространяется на функцию, в которой произошел сбой (но не обязательно он был вызван). Одноуровневые вызовы не отображаются в трассировке стека.

Языковая поддержка

[ редактировать ]

Многие языки программирования, включая Java [3] и С# , [4] имеют встроенную поддержку получения текущей трассировки стека с помощью системных вызовов. До std::stacktrace был добавлен в стандартную библиотеку как контейнер для std::stacktrace_entryВ версиях до C++23 для этого нет встроенной поддержки, но пользователи C++ могут получать трассировки стека, например, с помощью stacktrace библиотеки . В JavaScript исключения содержат stack свойство, содержащее стек из того места, куда он был брошен.

Например, следующая программа Python содержит ошибку.

def   a  ():      i   =   0      j   =   b  (  i  )      return   j  def   b  (  z  ):      k   =   5      if   z   ==   0  :          c  ()      return   k   +   z  def   c  ():      error  ()  a  () 

Запуск программы под управлением стандартного интерпретатора Python приводит к следующему сообщению об ошибке.

Traceback (последний вызов последний):   Файл  «tb.py»  , строка  15  , в  <module>      a  ()   Файл  «tb.py»  , строка  3  , в  a      j   =   b  (  i  )   Файл  «tb.py»  , строка  9  , в  b      c  ()   Файл  «tb.py»  , строка  13  ,  c      ошибка  ()  NameError  :  имя «ошибка» не определено 

Трассировка стека показывает, где возникает ошибка, а именно в c функция. Это также показывает, что c функция была вызвана b, который был вызван a, который, в свою очередь, вызывался кодом в строке 15 (последней строке) программы. Записи активации для каждой из этих трех функций будут расположены в стеке таким образом, чтобы a функция будет занимать нижнюю часть стека, а c функция будет занимать вершину стека.

В Java трассировку стека можно сбросить вручную с помощью Thread.dumpStack()[5] Возьмите следующий ввод:

общественный   класс   Main   {    public   static   void   main  (  String   args  []  )   {      demo  ();    }    Статическая   недействительная   демонстрация  ()   {      demo1  ();    }    static   void   demo1  ()   {      demo2  ();    }    static   void   demo2  ()   {      demo3  ();    }    Статическая   недействительность   demo3  ()   {      Тема  .  дампСтек  ();    }  } 

В исключении функции перечислены в порядке убывания, поэтому самый внутренний вызов идет первым.

Ява  .   окна  Исключение  :   стека   трассировка          в   Java  .   окна  Нить  .  dumpStack  (  Thread.java:1336  )          в   Main  .  demo3  (  Main  .  java  :  15  )          в   Main  .  demo2  (  Main  .  java  :  12  )          в   Main  .  demo1  (  Main  .  java  :  9  )          в   Main  .  демо  (  Main.java:6  )          в   Main  .  основной  (  Main  .  java  :  3  ) 

И C , и C++ (до C++23 ) не имеют встроенной поддержки получения трассировки стека, но такие библиотеки, как glibc и boost, предоставляют эту функциональность. [6] [7] В этих языках некоторые оптимизации компилятора могут влиять на информацию стека вызовов, которую можно восстановить во время выполнения. Например, встраивание может привести к отсутствию кадров стека, оптимизация хвостового вызова может заменить один кадр стека другим, а удаление указателя кадра может помешать инструментам анализа стека вызовов правильно интерпретировать содержимое стека вызовов. [6]

Например, glibc 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 ] 

Начиная с C++23 , трассировки стека можно сбрасывать вручную, печатая значение, возвращаемое статической функцией-членом. std::stacktrace::current(): [8]

std  ::  cout   <<   std  ::  stacktrace  ::  current  ()   <<   '\n'  ; 

Ржавчина

[ редактировать ]

В Rust есть два типа ошибок. паники Функции, использующие макрос , «невосстановимы», и текущий поток станет отравленным из-за разматывания стека. Функции, которые возвращают std::result::Result являются «восстанавливаемыми» и с ними можно обращаться корректно. [9] Однако исправимые ошибки не могут генерировать трассировку стека, поскольку они добавляются вручную, а не являются результатом ошибки времени выполнения.

По состоянию на июнь 2021 года в Rust имеется экспериментальная поддержка трассировки стека при неисправимых ошибках. Rust поддерживает вывод на поток stderr , когда поток паникует, но это необходимо включить, установив параметр RUST_BACKTRACE переменная среды . [10]

Когда эта функция включена, такие обратные трассировки выглядят так, как показано ниже: сначала самый последний вызов.

поток   '  main  '   запаниковал   при   '  execute_to_panic  '  ,   main  .  rs  :  3  стека   трассировки  :    0  :  std  ::  sys  ::  imp  ::  backtrace  ::  трассировка  ::  imp  ::  unwind_backtrace     1  :  std  ::  паника  ::  default_hook  ::  {{  замыкание  }}     2  :  std  ::  паника  ::  default_hook     3  :  std  : :  паника  ::  ржавчина_паника_с_хуком     4  :  станд  ::  паника  ::  начало_паника     5  :  фьючерсы  ::  Task_impl  ::  с     6  :  фьючерсы  ::  Task_impl  ::  парк  ..  . 

См. также

[ редактировать ]
  1. ^ «Руководство по libc: обратные трассировки» . gnu.org . Проверено 8 июля 2014 г.
  2. ^ «traceback — Распечатать или получить обратную трассировку стека» . python.org . Проверено 8 июля 2014 г.
  3. ^ «Поток (Java SE 16 и JDK 16)» . Стандартная версия платформы Java и пакет разработки Java версии 16. Спецификация API . 04.03.2021 . Проверено 4 июля 2021 г.
  4. ^ «Свойство Environment.StackTrace (система)» . Документы Майкрософт . 07.05.2021 . Проверено 4 июля 2021 г.
  5. ^ «Поток (платформа Java SE 8)» . docs.oracle.com . Проверено 15 июня 2021 г.
  6. ^ Перейти обратно: а б «Обратные трассировки (Библиотека GNU C)» . www.gnu.org . Проверено 15 июня 2021 г.
  7. ^ «Начало работы — 1.76.0» . www.boost.org . Проверено 15 июня 2021 г.
  8. ^ «Рабочий проект стандарта языка программирования C++» (PDF) . open-std.org . ИСО/МЭК. 2021-10-23. п. 766.
  9. ^ "размотка рустономикона - Rust" . doc.rust-lang.org .
  10. ^ "std::backtrace — Rust" . doc.rust-lang.org . Проверено 15 июня 2021 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 215bef72a4ccac0cced72cd966e5f425__1713782340
URL1:https://arc.ask3.ru/arc/aa/21/25/215bef72a4ccac0cced72cd966e5f425.html
Заголовок, (Title) документа по адресу, URL1:
Stack trace - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)