Перейти к содержимому

Stack trace что это

  • автор:

Что такое трассировка стека?

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

const func1 = () =>  throw Error('func1 error!'); >; const func2 = () =>  func1(); >; const func3 = () =>  func2(); >; try  func3(); > catch (e)  console.log(e); > // Вывод будет следующим (вместо anonymous будет имя файла с кодом, я запускал в консоли браузера) // Error: func1 error! // at func1 (:3:9) // at func2 (:8:3) // at func3 (:13:3) // at :17:3 

В коде у нас три функции, каждая из которых вызывает другую, последняя ( func1 ) внутри выбрасывает ошибку. Получается такая цепочка вызовов: func3 -> func2 -> func1 . Внутри блока try catch мы поймали ошибку и распечатали. По ней видно, что текст ошибки содержит не только то значение, переданное в Error() , но и имена функций, номера строк и позиций в строках, в которых была выброшена ошибка. Это и есть трассировка стека. По нему можно понять, что ошибка была внутри функции func1() , строка 3, позиция 9. Эта функция была вызвана внутри функции func2() , строка 8, позиция 3. Функция 2 была вызвана внутри func3() , строка 13, позиция 3. А функция func3() была вызвана на строке 17, позиция 3. Позиция указывает на номер символа (с которого начинается имя функции) с начала строки.

Что такое stack trace, и как с его помощью находить ошибки при разработке приложений?

Мне сказали, что это называется «трассировкой стека» или «stack trace». Что такое трассировка? Какую полезную информацию об ошибке в разрабатываемой программе она содержит? Немного по существу: довольно часто я вижу вопросы, в которых начинающие разработчики, получая ошибку, просто берут трассировки стека и какой-либо случайный фрагмент кода без понимания, что собой представляет трассировка и как с ней работать. Данный вопрос предназначен специально для начинающих разработчиков, которым может понадобиться помощь в понимании ценности трассировки стека вызовов. Перевод вопроса: «What is a stack trace, and how can I use it to debug my application errors?» @Rob Hruska

Отслеживать
123k 24 24 золотых знака 126 126 серебряных знаков 303 303 бронзовых знака
задан 7 апр 2016 в 10:45
Nicolas Chabanovsky Nicolas Chabanovsky
51.4k 86 86 золотых знаков 267 267 серебряных знаков 505 505 бронзовых знаков
ассоциация: stackoverflow.com/questions/3988788
24 фев 2017 в 9:10

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Простыми словами, трассировка стека – это список методов, которые были вызваны до момента, когда в приложении произошло исключение.

Простой случай

В указанном примере мы можем точно определить, когда именно произошло исключение. Рассмотрим трассировку стека:

Exception in thread "main" java.lang.NullPointerException at com.example.myproject.Book.getTitle(Book.java:16) at com.example.myproject.Author.getBookTitles(Author.java:25) at com.example.myproject.Bootstrap.main(Bootstrap.java:14) 

Это пример очень простой трассировки. Если пойти по списку строк вида «at…» с самого начала, мы можем понять, где произошла ошибка. Мы смотрим на верхний вызов функции. В нашем случае, это:

at com.example.myproject.Book.getTitle(Book.java:16) 

Для отладки этого фрагмента открываем Book.java и смотрим, что находится на строке 16 :

public String getTitle()

Это означает то, что в приведенном фрагменте кода какая-то переменная (вероятно, title ) имеет значение null .

Пример цепочки исключений

Иногда приложения перехватывают исключение и выбрасывают его в виде другого исключения. Обычно это выглядит так:

try < . >catch (NullPointerException e)

Трассировка в этом случае может иметь следующий вид:

Exception in thread "main" java.lang.IllegalStateException: A book has a null property at com.example.myproject.Author.getBookIds(Author.java:38) at com.example.myproject.Bootstrap.main(Bootstrap.java:14) Caused by: java.lang.NullPointerException at com.example.myproject.Book.getId(Book.java:22) at com.example.myproject.Author.getBookIds(Author.java:35) . 1 more 

В этом случае разница состоит в атрибуте «Caused by» («Чем вызвано»). Иногда исключения могут иметь несколько секций «Caused by». Обычно необходимо найти исходную причину, которой оказывается в самой последней (нижней) секции «Caused by» трассировки. В нашем случае, это:

Caused by: java.lang.NullPointerException  

Аналогично, при подобном исключении необходимо обратиться к строке 22 книги Book.java , чтобы узнать, что вызвало данное исключение – NullPointerException .

Еще один пугающий пример с библиотечным кодом

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

javax.servlet.ServletException: Произошло что–то ужасное at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) Caused by: com.example.myproject.MyProjectServletException at com.example.myproject.MyServlet.doPost(MyServlet.java:169) at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30) . 27 more Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [com.example.myproject.MyEntity] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2329) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2822) at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93) at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705) at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693) at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689) at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344) at $Proxy19.save(Unknown Source) at com.example.myproject.MyEntityService.save(MyEntityService.java:59)  

В этом примере приведен далеко не полный стек вызовов. Что вызывает здесь наибольший интерес, так это поиск функций из нашего кода – из пакета com.example.myproject . В предыдущем примере мы сначала хотели отыскать «первопричину», а именно:

Caused by: java.sql.SQLException 

Однако все вызовы методов в данном случае относятся к библиотечному коду. Поэтому мы перейдем к предыдущей секции «Caused by» и найдем первый вызов метода из нашего кода, а именно:

at com.example.myproject.MyEntityService.save(MyEntityService.java:59) 

Аналогично предыдущим примерам, необходимо обратить внимание на MyEntityService.java , строка 59 : именно здесь появилась ошибка (в данном случае ситуация довольно очевидная, так как об ошибке сообщает SQLException , но в этом вопросе мы рассматриваем именно процедуру отладки с помощью трассировки).

Что такое stacktrace?

Всем привет
Гуру программирования, подскажите плз:
Насколько корректно говорит stacktrace о выхлопе питоновского скрипта (errors). Нашел определение на вики, там говорится что stacktrace это вывод переменных кучи\стэка в момент исполнения. Моих "школярских" познаний в программровании хватает на то, чтобы вспомнить что стэк\куча - сущности употребляемые в объектных языках, а питон интерпретируемый. Отсюда вопрос - насколько корректно говорить про stacktrace если говорить и логировании ошибок в питоне
Спасибо

  • Вопрос задан более трёх лет назад
  • 11134 просмотра

Комментировать
Решения вопроса 1

leahch

Я мастер на все руки, я козлик Элек Мэк 🙂

Да, стектрейс это последовательность вызовов и состояние окружения в некоторой точке программы. И не важно, интерпретатор или система показывают это состояние - это стектрейс.
Даже в языках, которые реализуют парадигму машины состяний есть подобие стектрейса. Это текущее состояние, и условие перехода.

Ответ написан более трёх лет назад
Комментировать
Нравится 4 Комментировать
Ответы на вопрос 1

"Объектные" языки и интерпретируемые это тоже самое, что тёплое и мягкое.
Язык может быть объектно-ориентированным и в тоже время интерпретируемым. А может быть процедурным, но компилируемым. Это не взаимоисключающие свойства.

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

Stack Trace Класс

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Представляет трассировку стека — упорядоченный набор из одного или нескольких кадров стека.

public ref class StackTrace sealed
public ref class StackTrace
public sealed class StackTrace
public class StackTrace
[System.Serializable] public class StackTrace
[System.Serializable] [System.Runtime.InteropServices.ComVisible(true)] public class StackTrace
type StackTrace = class
[] type StackTrace = class
[] [] type StackTrace = class
Public NotInheritable Class StackTrace
Public Class StackTrace

Наследование
StackTrace

Примеры

В следующем консольном приложении показано, как создать простой StackTrace и выполнить итерацию по его кадрам для получения отладочные и диагностические сведения.

#using using namespace System; using namespace System::Diagnostics; ref class StackTraceSample < private: ref class MyInternalClass < public: void ThrowsException() < try < throw gcnew Exception( "A problem was encountered." ); >catch ( Exception^ e ) < // Create a StackTrace that captures // filename, line number, and column // information for the current thread. StackTrace^ st = gcnew StackTrace( true ); String^ stackIndent = ""; for ( int i = 0; i < st->FrameCount; i++ ) < // Note that at this level, there are five // stack frames, one for each method invocation. StackFrame^ sf = st->GetFrame( i ); Console::WriteLine(); Console::WriteLine( "Method: ", stackIndent, sf->GetMethod() ); Console::WriteLine( "File: ", stackIndent, sf->GetFileName() ); Console::WriteLine( "Line Number: ", stackIndent, sf->GetFileLineNumber().ToString() ); stackIndent = String::Concat( stackIndent, " " ); > throw e; > > >; protected: void MyProtectedMethod() < MyInternalClass^ mic = gcnew MyInternalClass; mic->ThrowsException(); > public: void MyPublicMethod() < MyProtectedMethod(); >>; int main() < StackTraceSample^ sample = gcnew StackTraceSample; try < sample->MyPublicMethod(); > catch ( Exception^ ) < // Create a StackTrace that captures // filename, line number, and column // information for the current thread. StackTrace^ st = gcnew StackTrace( true ); for ( int i = 0; i < st->FrameCount; i++ ) < // For an executable built from C++, there // are two stack frames here: one for main, // and one for the _mainCRTStartup stub. StackFrame^ sf = st->GetFrame( i ); Console::WriteLine(); Console::WriteLine( "High up the call stack, Method: ", sf->GetMethod()->ToString() ); Console::WriteLine( "High up the call stack, Line Number: ", sf->GetFileLineNumber().ToString() ); > > > /* This console application produces the following output when compiled with the Debug configuration. Method: Void ThrowsException() File: c:\samples\stacktraceframe\myclass.cpp Line Number: 20 Method: Void MyProtectedMethod() File: c:\samples\stacktraceframe\myclass.cpp Line Number: 45 Method: Void MyPublicMethod() File: c:\samples\stacktraceframe\myclass.cpp Line Number: 50 Method: Int32 main() File: c:\samples\stacktraceframe\myclass.cpp Line Number: 56 Method: UInt32 _mainCRTStartup() File: Line Number: 0 High up the call stack, Method: Int32 main() High up the call stack, Line Number: 62 High up the call stack, Method: UInt32 _mainCRTStartup() High up the call stack, Line Number: 0 This console application produces the following output when compiled with the Release configuration. Method: Void ThrowsException() File: Line Number: 0 Method: Int32 main() File: Line Number: 0 Method: UInt32 _mainCRTStartup() File: Line Number: 0 High up the call stack, Method: Int32 main() High up the call stack, Line Number: 0 High up the call stack, Method: UInt32 _mainCRTStartup() High up the call stack, Line Number: 0 */ 
using System; using System.Diagnostics; class StackTraceSample < [STAThread] static void Main(string[] args) < StackTraceSample sample = new StackTraceSample(); try < sample.MyPublicMethod(); >catch (Exception) < // Create a StackTrace that captures // filename, line number, and column // information for the current thread. StackTrace st = new StackTrace(true); for(int i =0; i< st.FrameCount; i++ ) < // Note that high up the call stack, there is only // one stack frame. StackFrame sf = st.GetFrame(i); Console.WriteLine(); Console.WriteLine("High up the call stack, Method: ", sf.GetMethod()); Console.WriteLine("High up the call stack, Line Number: ", sf.GetFileLineNumber()); > > > public void MyPublicMethod () < MyProtectedMethod(); >protected void MyProtectedMethod () < MyInternalClass mic = new MyInternalClass(); mic.ThrowsException(); >class MyInternalClass < public void ThrowsException() < try < throw new Exception("A problem was encountered."); >catch (Exception e) < // Create a StackTrace that captures filename, // line number and column information. StackTrace st = new StackTrace(true); string stackIndent = ""; for(int i =0; i< st.FrameCount; i++ ) < // Note that at this level, there are four // stack frames, one for each method invocation. StackFrame sf = st.GetFrame(i); Console.WriteLine(); Console.WriteLine(stackIndent + " Method: ", sf.GetMethod() ); Console.WriteLine( stackIndent + " File: ", sf.GetFileName()); Console.WriteLine( stackIndent + " Line Number: ", sf.GetFileLineNumber()); stackIndent += " "; > throw e; > > > > /* This console application produces the following output when compiled with the Debug configuration. Method: Void ThrowsException() File: c:\samples\stacktraceframe\myclass.cs Line Number: 59 Method: Void MyProtectedMethod() File: c:\samples\stacktraceframe\myclass.cs Line Number: 45 Method: Void MyPublicMethod() File: c:\samples\stacktraceframe\myclass.cs Line Number: 39 Method: Void Main(System.String[]) File: c:\samples\stacktraceframe\myclass.cs Line Number: 13 High up the call stack, Method: Void Main(System.String[]) High up the call stack, Line Number: 20 This console application produces the following output when compiled with the Release configuration. Method: Void ThrowsException() File: Line Number: 0 Method: Void Main(System.String[]) File: Line Number: 0 High up the call stack, Method: Void Main(System.String[]) High up the call stack, Line Number: 0 */ 
Imports System.Diagnostics Class StackTraceSample _ Public Shared Sub Main() Dim sample As New StackTraceSample() Try sample.MyPublicMethod() Catch ' Create a StackTrace that captures ' filename, line number, and column ' information for the current thread. Dim st As New StackTrace(True) Dim i As Integer For i = 0 To st.FrameCount - 1 ' Note that high up the call stack, there is only ' one stack frame. Dim sf As StackFrame = st.GetFrame(i) Console.WriteLine() Console.WriteLine("High up the call stack, Method: ", _ sf.GetMethod()) Console.WriteLine("High up the call stack, Line Number: ", _ sf.GetFileLineNumber()) Next i End Try End Sub Public Sub MyPublicMethod() MyProtectedMethod() End Sub Protected Sub MyProtectedMethod() Dim mic As New MyInternalClass() mic.ThrowsException() End Sub Class MyInternalClass Public Sub ThrowsException() Try Throw New Exception("A problem was encountered.") Catch e As Exception ' Create a StackTrace that captures filename, ' line number and column information. Dim st As New StackTrace(True) Dim stackIndent As String = "" Dim i As Integer For i = 0 To st.FrameCount - 1 ' Note that at this level, there are four ' stack frames, one for each method invocation. Dim sf As StackFrame = st.GetFrame(i) Console.WriteLine() Console.WriteLine(stackIndent + " Method: ", _ sf.GetMethod()) Console.WriteLine(stackIndent + " File: ", _ sf.GetFileName()) Console.WriteLine(stackIndent + " Line Number: ", _ sf.GetFileLineNumber()) stackIndent += " " Next i Throw e End Try End Sub End Class End Class ' This console application produces the following output when ' compiled with the Debug configuration. ' ' Method: Void ThrowsException() ' File: c:\pp\samples\stacktraceframe\myclass.vb ' Line Number: 55 ' ' Method: Void MyProtectedMethod() ' File: c:\pp\samples\stacktraceframe\myclass.vb ' Line Number: 42 ' ' Method: Void MyPublicMethod() ' File: c:\pp\samples\stacktraceframe\myclass.vb ' Line Number: 37 ' ' Method: Void Main(System.String[]) ' File: c:\pp\samples\stacktraceframe\myclass.vb ' Line Number: 13 ' ' High up the call stack, Method: Void Main(System.String[]) ' High up the call stack, Line Number: 18 ' ' ' This console application produces the following output when ' compiled with the Release configuration. ' ' Method: Void ThrowsException() ' File: ' Line Number: 0 ' ' Method: Void Main(System.String[]) ' File: ' Line Number: 0 ' ' High up the call stack, Method: Void Main() ' High up the call stack, Line Number: 0 ' 

Комментарии

StackTrace Сведения будут наиболее информативными в конфигурациях сборки отладки. По умолчанию отладочные сборки содержат отладочные символы, а сборки выпуска — нет. Отладочные символы содержат большую часть файлов, имени метода, номера строк и столбцов, используемых при конструировании StackFrame объектов и StackTrace .

StackTrace может не сообщать о количестве вызовов методов, как ожидалось, из-за преобразований кода, которые происходят во время оптимизации.

Конструкторы

Инициализирует новый экземпляр класса StackTrace из фрагмента вызывающего оператора.

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

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта исключения.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта исключения и дополнительно может собирать сведения об источнике.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта, пропуская указанное число фрагментов.

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

Создает трассировку стека на основе набора StackFrame объектов .

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

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

Инициализирует новый экземпляр класса StackTrace, содержащий один фрагмент.

Является устаревшей.
Является устаревшей.

Инициализирует новый экземпляр класса StackTrace для определенного потока и дополнительно может собирать сведения об источнике.

Не используйте эту перегрузку конструктора.

Поля

Определяет значение по умолчанию для числа методов, которые нужно пропустить в трассировке стека. Это поле является константой.

Свойства

Возвращает число фрагментов в трассировке стека.

Методы

Определяет, равен ли указанный объект текущему объекту.

Возвращает указанный кадр стека.

Возвращает копию всех кадров стека в текущей трассировке стека.

Служит хэш-функцией по умолчанию.

Возвращает объект Type для текущего экземпляра.

Создает неполную копию текущего объекта Object.

Создает доступное для чтения представление трассировки стека.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *