【发布时间】:2014-10-08 17:26:08
【问题描述】:
我有一个实现IDisposable 的类,因为它使用来自 GDI+ 的图像资源(Bitmap 类)。我用它来包装所有花哨的LockBits/UnlockBits。它工作正常,无论是当我调用Dispose() 还是使用using 语句时。
但是,如果我让程序终止而不进行处理,我会得到一个System.AccessViolationException。直觉上,我认为 GC 会像我一样调用Dispose,并且对象会优雅地释放资源,但事实并非如此。为什么?
这是IDisposable 代码:
private bool _disposing = false;
~QuickBitmap() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool safeDispose) {
if (_disposing)
return;
SaveBits(); // private wrapper to UnlockBits
bytes = null; // byte[] of the image
bmpData = null; // BitmapData object
if (safeDispose && bm != null) {
bm.Dispose(); // Bitmap object
bm = null;
}
_disposing = true;
}
这是正常工作的时候:
using (var qbm = new QuickBitmap("myfile.jpg"))
{
// use qbm.GetPixel/qbm.SetPixel at will
}
当它不起作用时:
public static void Main (string[] args) {
// this is just an example, simply constructing the object and doing nothing will throw the exception
var qbm = new QuickBitmap(args[0]);
qbm.SetPixel(0, 0, Color.Black);
qbm.Save();
}
完整的例外是(没有内部例外):
An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
即使在不同的机器上,复制也是 100%。我确实知道我们应该使用using 或Dispose(),不使用它是不好的,所有这些东西。我只想知道:为什么会这样?为什么内存被“保护”?我违反了哪种访问权限?
【问题讨论】:
-
只是好奇……你为什么认为
LockBits是“噱头”? -
@EdS。因为它要求我继续使用
IntPtr。我使用这个类来避免在更高级别的类中使用IntPtr。 -
您没有遵循规定的 Dispose 模式。
-
对我来说几乎不像是一个“噱头”,但还可以
-
有一个模式可以正确地创建一个对象,它同时具有一个disposer和一个finalizer,这个代码真的不是它的一个例子。规则一是除非您是垃圾收集器方面的专家,否则不要编写终结器。成为 GC 专家后,您首先会知道是否需要实现终结器,其次会知道如何安全地执行此操作。