Безопасное использование Marshal.Copy из необработанных растровых данных в управляемый массив - PullRequest
6 голосов
/ 05 января 2010

Я недавно отправил вопрос о том, как у моей программы произошла утечка памяти: см. здесь . Теперь я отслеживал это специально для некоторого кода, в котором я копирую необработанные байты объекта Bitmap в управляемый массив. Соответствующий код:

public class FastBitmap
{
    ...
    private byte[] rgbValues;
    private int height;
    private int width;
    private Bitmap image;

    public FastBitmap(Bitmap plainBitmap)
    {
        width = plainBitmap.Width;
        height = plainBitmap.Height;
        image = new Bitmap(plainBitmap);
        LockPixels(new Rectangle(0, 0, image.Width, image.Height));
    }

    private void LockPixels(Rectangle area)
    {
        if (locked)
            return;
        locked = true;
        BitmapData bitmapData = image.LockBits(area, ImageLockMode.ReadWrite,
                                PixelFormat.Format24bppRgb);
        IntPtr ptr = bitmapData.Scan0;
        int stride = bitmapData.Stride;
        int numBytes = image.Width * image.Height * 3;
        rgbValues = new byte[numBytes];
        for (int r = 0; r < image.Height; ++r)
        Marshal.Copy(new IntPtr((int)ptr + stride * r), 
                             rgbValues, image.Width * 3 * r, image.Width * 3);
    }
}

Так что это весь объем кода, который вызывает восстановление памяти, и я думаю, что это как-то связано с Marshal.Copy (), хотя я предполагал, что, поскольку я копировал из Bitmap (очищен сам по себе?) к управляемому массиву проблем не было.

Итак, вопрос: нужно ли очищать объект Bitmap, либо через интерфейс IDisposable, либо что-то подобное. Что (если есть что-то) по своей сути неправильно с использованием Marshal.Copy () в этой ситуации, и где я могу устранить проблему?

Спасибо

Точно так же вы знаете, что я проверил следующий код, чтобы убедиться, что это действительно вызывает проблему:

Bitmap bmp = new Bitmap(1000, 1000);
for (int n = 0; n < 100; ++n)
{
   FastBitmap fb = new FastBitmap(bmp);
}

В начале и конце этой последовательности общее использование памяти увеличилось примерно на 320 Мб и не исчезает, независимо от того, как долго вы ждете.

1 Ответ

8 голосов
/ 05 января 2010

Вы забыли вызвать image.UnlockBits (bitmapData);

...