内存压缩后IntPtr是否仍然有效?

时间:2013-07-24 13:41:55

标签: c# .net memory bitmap intptr

我在.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更好。

2 个答案:

答案 0 :(得分:2)

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

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

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

  • 您正在访问位图之外的内存(例如,坐标不正确)。
  • 您正在UnlockBits()调用
  • 后访问位图数据

答案 1 :(得分:2)

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

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

您应该寻找的问题是在位图的末尾运行,您使用的是不安全的指针,因此您将无法获得友好的IndexOutOfRangeException。然而,AV应该是下一个最好的诊断,假设它实际上发生在被锁定的代码内部。指针类型和像素格式之间的不匹配可能是一个原因。除此之外,片段中的代码太少了。