Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Как избавится от утечки памяти

#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); }

Комментариев нет:

Отправить комментарий