【问题标题】:Memory allocated with Marshal.AllocHGlobal is getting corrupted?使用 Marshal.AllocHGlobal 分配的内存已损坏?
【发布时间】:2013-03-08 19:16:34
【问题描述】:

我需要创建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 显示它时整个程序崩溃 - 完全随机的一个或另一个。

【问题讨论】:

  • 垃圾收集器可能在您的位图对象周围移动。也许你应该pin
  • 您能详细说明一下这是如何工作的吗?我对如何实现这一点感到困惑,并且不确定如何固定对象会阻止非托管内存被破坏?

标签: memory bitmap gdi+ system.drawing pixels


【解决方案1】:

内存被破坏的原因是因为我在完成FastBitmap之后使用Bitmap.Clone复制_bitmapObject

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

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

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

Bitmap clone = new Bitmap(bitmapToClone);

它确实将像素数据复制到其他地方,从而可以释放旧内存。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 2019-09-23
    • 2015-05-16
    • 2012-07-27
    相关资源
    最近更新 更多