Windows stack trace function

Stack Trace Класс

Определение

Представляет трассировку стека — упорядоченный набор из одного или нескольких кадров стека. Represents a stack trace, which is an ordered collection of one or more stack frames.

Примеры

В следующем консольном приложении показано, как создать простой объект StackTrace и выполнить итерацию по его кадрам для получения сведений об отладке и диагностике. The following console application demonstrates how to create a simple StackTrace and iterate through its frames to obtain debugging and diagnostic information.

Комментарии

StackTrace информация будет наиболее информативной с отладочными конфигурациями сборки. StackTrace information will be most informative with Debug build configurations. По умолчанию отладочные сборки содержат отладочные символы, а сборки выпуска — нет. By default, Debug builds include debug symbols, while Release builds do not. Отладочные символы содержат большую часть сведений о файле, имени метода, номере строки и столбцах, используемых при построении StackFrame и StackTrace объектах. The debug symbols contain most of the file, method name, line number, and column information used in constructing StackFrame and StackTrace objects.

StackTrace может не сообщать о количестве вызовов методов, как ожидалось, из-за преобразований кода, происходящих во время оптимизации. StackTrace might not report as many method calls as expected, due to code transformations that occur during optimization.

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

Инициализирует новый экземпляр класса StackTrace из фрагмента вызывающего оператора. Initializes a new instance of the StackTrace class from the caller’s frame.

Инициализирует новый экземпляр класса StackTrace из фрагмента вызывающего оператора и дополнительно может собирать сведения об источнике. Initializes a new instance of the StackTrace class from the caller’s frame, optionally capturing source information.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта исключения. Initializes a new instance of the StackTrace class using the provided exception object.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта исключения и дополнительно может собирать сведения об источнике. Initializes a new instance of the StackTrace class, using the provided exception object and optionally capturing source information.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта, пропуская указанное число фрагментов. Initializes a new instance of the StackTrace class using the provided exception object and skipping the specified number of frames.

Инициализирует новый экземпляр класса StackTrace с использованием предоставленного объекта исключения, пропуская заданное число фрагментов и дополнительно собирая сведения об источнике. Initializes a new instance of the StackTrace class using the provided exception object, skipping the specified number of frames and optionally capturing source information.

Инициализирует новый экземпляр класса StackTrace из фрагмента вызывающего оператора, пропуская заданное число фрагментов. Initializes a new instance of the StackTrace class from the caller’s frame, skipping the specified number of frames.

Инициализирует новый экземпляр класса StackTrace из фрагмента вызывающего оператора, пропуская заданное число фрагментов и дополнительно собирая сведения об источнике. Initializes a new instance of the StackTrace class from the caller’s frame, skipping the specified number of frames and optionally capturing source information.

Читайте также:  Windows near the floor

Инициализирует новый экземпляр класса StackTrace, содержащий один фрагмент. Initializes a new instance of the StackTrace class that contains a single frame.

Инициализирует новый экземпляр класса StackTrace для определенного потока и дополнительно может собирать сведения об источнике. Initializes a new instance of the StackTrace class for a specific thread, optionally capturing source information.

Не используйте эту перегрузку конструктора. Do not use this constructor overload.

Определяет значение по умолчанию для числа методов, которые нужно пропустить в трассировке стека. Defines the default for the number of methods to omit from the stack trace. Это поле является константой. This field is constant.

Свойства

Возвращает число фрагментов в трассировке стека. Gets the number of frames in the stack trace.

Методы

Определяет, равен ли указанный объект текущему объекту. Determines whether the specified object is equal to the current object.

(Унаследовано от Object) GetFrame(Int32)

Возвращает указанный кадр стека. Gets the specified stack frame.

Возвращает копию всех кадров стека в текущей трассировке стека. Returns a copy of all stack frames in the current stack trace.

Служит хэш-функцией по умолчанию. Serves as the default hash function.

(Унаследовано от Object) GetType()

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

(Унаследовано от Object) MemberwiseClone()

Создает неполную копию текущего объекта Object. Creates a shallow copy of the current Object.

(Унаследовано от Object) ToString()

Создает доступное для чтения представление трассировки стека. Builds a readable representation of the stack trace.

akihiroy / stack_trace.cpp

# include windows.h >
# define DBGHELP_TRANSLATE_TCHAR
# include DbgHelp.h >
void StackTrace ()
<
CONTEXT context = < 0 >;
# if defined(_M_X64)
RtlCaptureContext (&context);
# else
__asm call (x);
__asm x: pop eax;
__asm mov context. Eip , eax;
__asm mov context. Ebp , ebp;
__asm mov context. Esp , esp;
# endif
const HANDLE hProcess = :: GetCurrentProcess ();
const HANDLE hThread = :: GetCurrentThread ();
STACKFRAME64 stack = < 0 >;
stack. AddrPC . Offset = context. Eip ;
stack. AddrPC . Mode = AddrModeFlat;
stack. AddrStack . Offset = context. Esp ;
stack. AddrStack . Mode = AddrModeFlat;
stack. AddrFrame . Offset = context. Ebp ;
stack. AddrFrame . Mode = AddrModeFlat;
SymSetOptions ( SymGetOptions () | SYMOPT_UNDNAME);
SYMBOL_INFO *pSymbol = (SYMBOL_INFO *) calloc ( sizeof (SYMBOL_INFO) + sizeof (TCHAR) * 255 , 1 );
std::wstring stack_trace;
for ( int frame = 0 ; ; ++frame)
<
BOOL result = StackWalk64 (IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stack, &context, NULL , SymFunctionTableAccess64, SymGetModuleBase64, NULL );
pSymbol-> SizeOfStruct = sizeof (SYMBOL_INFO);
pSymbol-> MaxNameLen = 256 ;
DWORD64 displacement;
SymFromAddr (hProcess, stack. AddrPC . Offset , &displacement, pSymbol);
if (!stack_trace. empty ()) stack_trace. append ( 1 , L ‘ \n ‘ );
stack_trace. append (pSymbol-> Name );
if (!result) <
break ;
>
>
free (pSymbol);
wprintf ( L» %s » , stack_trace. c_str ());
>

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

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

Иногда при запуске своего приложения я получаю подобную ошибку:

Читайте также:  Ошибка при обновление windows 800b0001

Мне сказали, что это называется «трассировкой стека» или «stack trace». Что такое трассировка? Какую полезную информацию об ошибке в разрабатываемой программе она содержит?

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

1 ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

How do I find the stack trace in Visual Studio?

I ask because I couldn’t find the stack trace in Visual Studio, while debugging an exception that occurred.

7 Answers 7

While debugging, Go to Debug -> Windows -> Call Stack

While debugging, when you hit a break-point.

The default shortcut key is Ctrl-Alt-C.

Do you mean finding a stack trace of the thrown exception location? That’s either Debug/Exceptions, or better — Ctrl-Alt-E. Set filters for the exceptions you want to break on.

There’s even a way to reconstruct the thrower stack after the exception was caught, but it’s really unpleasant. Much, much easier to set a break on the throw.

Using the Call Stack Window

To open the Call Stack window in Visual Studio, from the Debug menu, choose Windows>Call Stack. To set the local context to a particular row in the stack trace display, double click the first column of the row.

Читайте также:  Windows не может открыть файл hosts

Consider this as the current update (Windows 10 (Version 1803) and Visual Studio 2017): I was unable to view the stack trace window and did find an option/menu item to view it. On investigating further, it seems this feature is not available on Windows 10. For further information please refer:

Copied from the above link: «This feature is not available in Windows 10, version 1507 and later versions of the WDK.»

For Visual Studio 2019, the shortcut (while debugging and stopped at a breakpoint) is:

Ctrl + Alt + C and now you can also use Ctrl + L

The screenshot is pretty old. Here is one for Visual Studio 2019 (under the debug menu):

Windows C++ stack trace from a running app

I saw an app, an SVN Visual Studio plugin, that displayed a beautiful readable stack trace, when it crashed.

I would love to add that to my application. How do I provide that? No emailing of the information, just a visual display is enough.

3 Answers 3

The core of the necessary code is StackWalk64 . To get much from that, you’ll also want/need to get symbol names with SymGetSymFromAddr64 (which requires SymLoadModule64 ) and (probably) SymGetLineFromAddr64 and GetThreadContext . If the target was written in C++, you’ll probably also want to use UnDecorateSymbolName . Along with those you’ll need a few ancillaries like SymInitialize , SymCleanup , and probably SymSetOptions .

Here’s a fairly minimal demo. The stack dump it produces is more utilitarian than beautiful, but presumably with the basics of doing the stack trace, you can display the results as you see fit:

I modified Jerry Coffin’s code as you see below. Modifications:

A. I was always missing the most important frame of all: the line that actually triggered the exception. Turns out this was because the «do» loop was moving to the next frame at the top instead of at the bottom.

B. I removed the threading stuff.

C. I simplified a few bits.

You should cut the «WinMain()» function at the bottom and instead put the __try .. __except stuff in your own ‘main/WinMain’ function. Also replace ‘YourMessage’ with your own function to display a message box or email it or whatever.

The symbolic information is stored inside a .pdb file, not the .exe. You need to give your users your .pdb file, and you need to ensure that their process can find it. See the string inside the code below — replace this with a folder that will work on the users’ machine, or NULL — NULL means it will search in the process’s current working directory. The .pdb file must have the exact same name on the users’ computer as it had when you ran your compiler — to configure this to something different, see «Properties > Linker > Debugging > Generate Program Database File».

Оцените статью