1

我在 .NET 中并使用指针来访问原始图像数据。目前,我正在使用以下方法存储对位图 Scan0(和 Stride)的引用:

BitmapData bmpData = bmp.LockBits(...);
*byte scan0 = (*byte)bmpData.Scan0;

有时我的程序会随机崩溃,并出现“尝试访问受保护的内存”之类的错误。我假设这是因为在 .NET GC 例行压缩内存后我的指针变得无效。因此,如果我使用IntPtr而不是*byte我当前使用的指针,那么指针在内存压缩后是否仍然有效?

BitmapData bmpData = bmp.LockBits(...);
IntPtr scan0 = bmpData.Scan0;

显然,几乎不可能对此进行测试,因为我无法复制我得到的“随机”内存错误,所以我试图找到一个理论上正确的解决方案,并希望它能纠正我的问题。

编辑:请不要开始讨论位图操作技术。我只是想知道是否IntPtr*byte.

4

2 回答 2

2

IntPtr是一个与指针大小相同的整数。它不会被 GC 跟踪。

LockBits()方法已经确保 GC 不会移动位图数据。

如果您遇到访问冲突,有两个可能的原因:

  • 您正在访问位图之外的内存(例如不正确的坐标)。
  • UnlockBits()通话后您正在访问位图数据
于 2013-07-24T13:59:20.717 回答
2

不,这不是位图像素数据的问题。它分配在非托管内存中,垃圾收集器无法触及它。它实际上是一个内存映射文件,加载或保存位图会锁定文件的原因。LockBits() 方法确保内存映射的文件被映射到内存并且视图是稳定的。这种优化是必需的,因为位图可能非常大,并且它们的内存不应该由页面文件支持。

Anyhoo,使用 byte* 或 IntPtr 是没有问题的,只要位图被锁定,它们指向的内存就可以保证是稳定的。

您应该寻找的问题是超出位图的末尾,您正在使用不安全的指针,因此您不会得到友好的 IndexOutOfRangeException。然而,AV应该是下一个最好的诊断,假设它实际上发生在被锁括起来的代码中。指针类型和像素格式不匹配可能是一个原因。代码片段中的代码太少,无法进行理论分析。

于 2013-07-24T14:16:01.370 回答