我的代码中有一些点,我只是创建一个新的Bitmap对象,如下所示:
bmpTile = new Bitmap(8, 8, PixelFormat.Format32bppArgb);
简单,对吗?出于某种原因,我随机在这样的行上获得异常。通过随机,我的意思是我不能在相同的事件序列之后在同一行上一致地重现相同的异常。我甚至无法为你们创建单元测试。
我得到的最常见的例外是:
ArgumentException: Parameter is not valid.
TargetSite: {Void .ctor(Int32, Int32, System.Drawing.Imaging.PixelFormat)}
下一个最常见的一个甚至没有从我的程序中给我一个堆栈跟踪:
AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
StackTrace:
at System.Drawing.SafeNativeMethods.Gdip.IntGdipDisposeImage(HandleRef image)
at System.Drawing.SafeNativeMethods.Gdip.GdipDisposeImage(HandleRef image)
at System.Drawing.Image.Dispose(Boolean disposing)
at System.Drawing.Image.Finalize()
TargetSite: {Int32 IntGdipDisposeImage(System.Runtime.InteropServices.HandleRef)}
看起来每当我尝试创建一个新的Bitmap时都会遇到问题,但为什么?我无处不在地使用LockBits和UnlockBits,但我总是成对地使用它们:我从不在没有后续UnlockBits的情况下调用LockBits。
那么什么可能导致Dispose()失败呢?
编辑:我应该提到它在第二次尝试时没有发生。它发生在第五次或第六次尝试时,意味着它已经处理了前四个或五个位图而没有问题。答案 0 :(得分:2)
这两个问题都有相同的根本原因。 LockBits()之后的代码破坏了非托管堆。通常在此类代码中使用指针或Marshal.Copy(),因此在位图边界外写入时无法进行诊断。当你幸运的时候,你只能得到一个AccessViolation。但更典型的是,直到稍后,当堆分配器尝试从堆中分配或释放块时,才会获得它们。由于崩溃位置与原始错误无关,因此很难诊断。