На выходных заходил я к своему другу new_s в гости и он показал мне интересную вещь. Ему по работе нужно было анализировать дамп памяти .net приложения, где он искал утечки памяти и другое аномальное поведение и показал мне, что при старте любого .net приложения окружение резервирует память для трех исключений:
И это нормальное поведение. Почему?
Я решил провести эксперимент, и, загрузив Visual Studio, создал простейшее консольное приложение Hello world:
Компиллируем это дело либо, можем скачать то же самое тут.
Теперь скачаем Debuggin Tools For Windows. Нам нужна утилита
Открываем ее и добавляем символы (pdb файл): File -> Symbol File Path и указываем наш .pdb файл
Дальше запускаем наше приложение (если из Visual Studio, то не в Debug Mode) и в WinDbg присоеденяемся к процессу: File->Attach to a Process

Выполняем команду:
для того, чтобы загрузить
Сделаем dump памяти, выполнил следующую команду:
Можно остановить Debug: Debug -> Stop Debuggin
И открыть наш memory dump: File -> Open Crash Damp и выбрав наш
Отфильтруем дамп, чтобы увидеть исключения командой:
И что мы видим? Вот они наши исключения:

Эти три исключения (
Так что если когда нибудь вам предстоит работать с дампом памяти .net приложений, не пугайтесь этих исключений, .net среда сама пробросит их, когда не будет хватать памяти либо буффер переполнен.
- ExecutionEngineException
- StackOverflowException
- OutOfMemoryException
И это нормальное поведение. Почему?
Я решил провести эксперимент, и, загрузив Visual Studio, создал простейшее консольное приложение Hello world:
using System;
namespace HelloWorld
{
class Program
{
static void Main()
{
Console.Write("Hello world!");
Console.ReadKey();
}
}
}
Компиллируем это дело либо, можем скачать то же самое тут.
Теперь скачаем Debuggin Tools For Windows. Нам нужна утилита
WinDbg
.Открываем ее и добавляем символы (pdb файл): File -> Symbol File Path и указываем наш .pdb файл
HelloWorld.pdb
. Также необходимо, загрузить символы для других сборок, так что создайте темповую директорию и в окне Symbol File Path
укажите что-то похожее на D:\WORK\Projects\Own\HelloWorld\HelloWorld\bin\Debug; SRV*D:\Temp\Symbols*http://msdl.microsoft.com/download/symbols
Дальше запускаем наше приложение (если из Visual Studio, то не в Debug Mode) и в WinDbg присоеденяемся к процессу: File->Attach to a Process

Выполняем команду:
.loadby sos mscorwks
для того, чтобы загрузить
sos.dll
расширение и позволить дебажить управляемый код.Сделаем dump памяти, выполнил следующую команду:
.dump /ma D:\Temp\HelloWorld.dmp
Можно остановить Debug: Debug -> Stop Debuggin
И открыть наш memory dump: File -> Open Crash Damp и выбрав наш
HelloWorld.dmp
Отфильтруем дамп, чтобы увидеть исключения командой:
!dumpheap -type Exception
И что мы видим? Вот они наши исключения:
7093fd68 1 84 System.ExecutionEngineException
7093fd1c 1 84 System.StackOverflowException
7093fcd0 1 84 System.OutOfMemoryException

Выводы
Эти три исключения (
ExecutionEngineException, StackOverflowException и OutOfMemoryException
) специально созданы при старте приложения, чтобы охватить такую ситуацию, как например когда у вас уже кончилась память и ее не хватает даже на создание OutOfMemory
исключения, так как это привело бы к еще одному OOM исключению. Точно также, если у вас уже переполнение стека, вы не можете создать StackOverflowException
, так как для этого нужно было бы вызвать его конструктор, что является невозможным при уже переполненном стеке.Так что если когда нибудь вам предстоит работать с дампом памяти .net приложений, не пугайтесь этих исключений, .net среда сама пробросит их, когда не будет хватать памяти либо буффер переполнен.