Bitmap.LockBits是否将位图“固定”到内存中?

我最近使用锁定的位图,并且一直“试图访问无效内存”错误。 这主要是因为位图已在内存中移动。 有些人使用GCHandle.Alloc()在CLR中分配内存并固定它。 Bitmap.LockBits()也这样做吗? 我不明白“锁定”内存和“固定”内存之间的区别。 你能解释术语和差异吗?

GCHandle.Alloc是一种更通用的方法,允许您为任何托管对象分配句柄并将其固定在内存中(或不固定)。 固定内存会阻止GC移动它,这在您必须将某些数据(例如数组)传递给非托管代码时尤其有用。

GCHandle.Alloc不会以任何方式帮助您访问位图的数据,因为固定此对象只会阻止托管对象移动(Bitmap对象)(并进行垃圾回收)。

然而,Bitmap是本机GDI +的BITMAP结构的包装器。 它不会将数据保存在您必须固定的任何托管数组中,它只是管理了GDI +位图对象的本机句柄。 因为Bitmap.LockBits是一种告诉这个位图的方式,你有兴趣访问它的内存,它只是GdipBitmapLockBits函数的包装器。 因此,您需要调用它更多地与您使用GDI +位图这一事实有关,而不是与您在使用GC的托管环境中工作的事实有关。

一旦你使用了LockBits你应该能够通过BitmapData.Scan0使用指针访问它的内存 – 它是数据第一个字节的地址。 你应该没有问题,因为你没有访问BitmapData.Scan0 + Height * Stride后面的内存。

当你完成时,记得UnlockBits

在您的情况下, attempted to access invalid memory错误很可能是由于您在代码的不安全部分进行的无效内存分配造成的,例如,分配的数组小于您尝试放入的像素数。

除非您的图像数据小于85000字节 ,否则也无需考虑固定对象,因为只有小于85K的对象将在内存中移动。

另一个故事是,如果您将对象传递给非托管代码,例如在c ++库中以便更快地处理。 在这种情况下,如果传递的图像超出范围并且将被垃圾收集,则很可能发生exception。 在这种情况下,您可以使用GCHandle.Alloc (imageArray,GCHandleType.Pinned); 如果您不再需要它,请致电免费。