Я использовал методологию , изложенную Шивпрасад Коирала для проверки утечек памяти из кода, работающего внутри приложения C# (VoiceAttack). В основном это включает в себя использование монитора производительности для отслеживания частных байтов приложения, а также байтов во всех кучах и сравнения этих счетчиков, чтобы оценить, есть ли утечка и какой тип (управляемый/неуправляемый). В идеале мне нужно протестировать вне Visual Studio, поэтому я использую этот метод.
Следующая часть кода создает приведенный ниже профиль памяти (имейте в виду, что код имеет немного другой формат по сравнению с Visual Studio, потому что это функция, содержащаяся в основном приложении C#):
public void main()
{
string FilePath = null;
using (FileDialog myFileDialog = new OpenFileDialog())
{
myFileDialog.Title = "this is the title";
myFileDialog.FileName = "testFile.txt";
myFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
myFileDialog.FilterIndex = 1;
if (myFileDialog.ShowDialog() == DialogResult.OK)
{
FilePath = myFileDialog.FileName;
var extension = Path.GetExtension(FilePath);
var compareType = StringComparison.InvariantCultureIgnoreCase;
if (extension.Equals(".txt", compareType) == false)
{
FilePath = null;
VA.WriteToLog("Selected file is not a text file. Action canceled.");
}
else
VA.WriteToLog(FilePath);
}
else
VA.WriteToLog("No file selected. Action canceled.");
}
VA.WriteToLog("done");
}
Вы можете видеть, что после выполнения этого кода частные байты не возвращаются к исходному количеству, а байты во всех кучах примерно постоянны, что означает, что есть часть неуправляемой памяти, которая не была освобождена. Выполнение одной и той же встроенной функции несколько раз подряд не приводит к дальнейшему увеличению максимального количества наблюдаемых закрытых байтов или невысвобожденной памяти. Когда основное приложение C# (VoiceAttack) закрывается, вся соответствующая память (включая память для приведенного выше кода) освобождается. Плохая новость заключается в том, что при нормальных обстоятельствах основное приложение может оставаться запущенным пользователем неопределенно долгое время, в результате чего выделенная память остается невысвобожденной.
На всякий случай я добавил этот же код в VS (с парой Thread.Sleep(5000)
, добавленной до и после блока using
для лучшего графического анализа) и создал исполняемый файл для отслеживания с помощью метода Performance Monitor, и результат тот же. Существует начальный скачок неуправляемой памяти для OpenFileDialog, и выделенная неуправляемая память никогда не возвращается к исходному значению.
Имеет ли смысл изложенная выше методика отслеживания памяти и утечек? Если ДА, можно ли что-нибудь сделать, чтобы правильно освободить неуправляемую память?