Marshal.AllocHGlobal分配的内存是否已损坏?

时间:2013-03-08 19:16:35

标签: memory bitmap gdi+ system.drawing pixels

我需要创建Bitmap个对象,可以直接访问其像素数据。

LockBits对我的需求来说太慢了 - 这对于快速重新创建(有时是大型)位图没有好处。

所以我有一个自定义FastBitmap对象。它引用了Bitmap对象和IntPtr,它指向位图中的位。

构造函数如下所示:

public FastBitmap(int width, int height)
{
    unsafe
    {
        int pixelSize = Image.GetPixelFormatSize(PixelFormat.Format32bppArgb) / 8;
        _stride = width * pixelSize;

        int byteCount = _stride * height;

        _bits = Marshal.AllocHGlobal(byteCount);

        // Fill image with red for testing
        for (int i = 0; i < byteCount; i += 4)
        {
            byte* pixel = ((byte *)_bits) + i;
            pixel[0] = 0;
            pixel[1] = 0;
            pixel[2] = 255;
            pixel[3] = 255;

        }

        _bitmapObject = new Bitmap(width, height, _stride, PixelFormat.Format32bppArgb, _bits); // All bits in this bitmap are now directly modifiable without LockBits. 

    }
}

分配的内存在解析器调用的清理函数中释放。

这可以,但不会很久。不知怎的,没有对位的任何进一步修改,分配的内存被破坏,这破坏了位图。有时,位图的大部分被随机像素替换,有时当我尝试用Graphics.DrawImage显示它时,整个程序崩溃 - 无论是一个还是另一个,完全随机。

1 个答案:

答案 0 :(得分:1)

内存损坏的原因是因为我在使用Bitmap.Clone后使用_bitmapObject复制了FastBitmap

Bitmap.Clone在调用时不会生成像素数据的新副本,或者至少在使用您自己的已分配数据创建Bitmap时就是这种情况。

相反,克隆似乎使用完全相同的像素数据,这对我来说是有问题的,因为我在克隆操作后释放像素数据内存,导致克隆的位图在内存用于其他事情时损坏。 / p>

我发现作为Bitmap.Clone的替代方案的第一个和当前的解决方案是使用:

Bitmap clone = new Bitmap(bitmapToClone);

将像素数据复制到其他地方,这样可以释放旧内存。

可能有更好/更快的方法来制作完全复制的克隆,但现在这是一个简单的解决方案。