#c_sharp #net #wpf
Собственно код (пример тестовый, но реальную аналогичную ситуацию моделирует на 100%):
public partial class MainWindow : Window
{
test meml;
public MainWindow()
{
InitializeComponent();
meml = new test();
}
private void button_Click(object sender, RoutedEventArgs e)
{
meml.Run();
}
}
public class test
{
public void Run()
{
for (int i = 0; i < 200; i++) RunMemoryLeak();
}
private void RunMemoryLeak()
{
unsafe
{
var ImgPointer = (void*)new Bitmap(700, 700).GetHbitmap();
}
}
}
Соответственно при нажатии на кнопку приложение "съедает" ~ 380мб (один Bitmap(700,
700) это ~ 1,9мб если умножить на 200 как раз выйдет объём откушаной памяти) Сборщик
мусора данную память не освобождает. Предупреждения GC о большом объёме выделенной
памяти в неуправляемом блоке (GC.AddMemoryPressure) не спасают. Зануление указателя
так же. Зануление объекта meml аналогично.
Моих знаний .Net'a не хватает, чтобы объяснить данную ситуацию. Кто знает, что тут
происходит? Где выделяется память и почему она не освобождается? И как данный код исправить/дополнить
чтобы многократный его вызов не приводил к OutOfMemoryException
PS: 15-ая студия, 10-ая винда, 4-ый фреймворк
Ответы
Ответ 1
GetHBitmap создает из вашего Bitmap старый добрый неуправляемый BITMAP из GDI, который никак не контролируется ни .NET, ни сборщиком мусора. Его нужно освобождать вручную. Об освобождении памяти из-под результата вызова GetHBitmap прямо сказано в MSDN по этому методу, с примером: Пользователь несет ответственность за вызов метода DeleteObject объекта GDI для высвобождения памяти, использованной точечным рисунком GDI private void DemonstrateGetHbitmap() { Bitmap bm = new Bitmap("Picture.jpg"); IntPtr hBitmap = bm.GetHbitmap(); // Do something with hBitmap. DeleteObject(hBitmap); }
Комментариев нет:
Отправить комментарий