我最近使用了锁定的位图,并且我一直在“尝试访问无效内存”错误。这主要是因为位图已在内存中移动。有些人使用GCHandle.Alloc()
在CLR中分配内存并固定它。 Bitmap.LockBits()
是否也这样做?我不明白“锁定”内存和“固定”内存之间的区别。你能解释术语和差异吗?
答案 0 :(得分:8)
GCHandle.Alloc
是一种更通用的方法,允许您为任何托管对象分配句柄并将其固定在内存中(或不固定)。固定内存会阻止GC移动它,这在您必须将某些数据(例如数组)传递给非托管代码时尤其有用。
GCHandle.Alloc
无法帮助您以任何方式访问位图数据,因为固定此对象只会阻止托管对象移动(Bitmap对象)(并进行垃圾回收)。
Bitmap是本机GDI + BITMAP
结构的包装器。它不会将数据保存在您必须固定的任何托管数组中,它只是管理了GDI +位图对象的本机句柄。因为Bitmap.LockBits
是一种告诉这个位图的方式,你有兴趣访问它的内存,它只是GdipBitmapLockBits
函数的包装器。因此,您需要调用它更多地与您使用GDI +位图的事实有关,而不是与您在使用GC的托管环境中工作的事实有关。
使用LockBits
之后,您应该可以使用BitmapData.Scan0
中的指针访问它的内存 - 它是数据第一个字节的地址。您不应该长时间遇到问题,因为您不能访问BitmapData.Scan0 + Height * Stride
后面的内存。
当你完成时记得UnlockBits
。
答案 1 :(得分:1)
在您的情况下,attempted to access invalid memory
错误很可能是由于您在代码的不安全部分进行的无效内存分配造成的,例如,分配的数组小于您尝试放入的像素数。< / p>
除非您的图像数据为less than 85000 Bytes,否则无需考虑固定对象,因为只有小于85K的对象才会在内存中移动。
另一个故事是,如果您将对象传递给非托管代码,例如在c ++库中以便更快地处理。在这种情况下,如果传递的图像超出范围并且将被垃圾收集,则很可能发生异常。在这种情况下,您可以使用GCHandle.Alloc (imageArray,GCHandleType.Pinned);
,如果您不再需要,请致电免费。