#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); }
Комментариев нет:
Отправить комментарий