我在循环中使用第二次运行此代码后获得了MDA(使用不同的file
参数:
byte[] encryptedData = File.ReadAllBytes(file); // before this line it throws, see exception below
long dataOffset;
using (var stream = new MemoryStream(encryptedData))
using (var reader = new BinaryReader(stream))
{
// ... read header information which is not encrypted
}
using (var stream = new MemoryStream(encryptedData))
{
stream.Seek(dataOffset, SeekOrigin.Begin);
using (var aesAlg = new AesCryptoServiceProvider())
using (var decryptor = aesAlg.CreateDecryptor(key, iv))
using (var csDecrypt = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
using (var reader = new BinaryReader(csDecrypt))
{
decrypted = reader.ReadBytes((int)(encryptedData.Length - dataOffset));
}
}
MDA如下:
“Microsoft.Win32.SafeHandles.SafeCapiKeyHandle”类型的SafeHandle或CriticalHandle无法正确释放值为0x000000001BEA9B50的句柄。这通常表示通过其他方式错误地释放了句柄(例如使用DangerousGetHandle提取句柄并直接关闭它或在其周围构建另一个SafeHandle。)
堆栈跟踪没有太多信息:
mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Dispose(bool disposing)+ 0x10 bytes mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Finalize()+ 0x1a bytes
我怀疑其中一个流或CryptoServiceProvider由于某种原因未发布。除此之外,代码运行良好,并做到了预期。 MDA在控件到达方法的第一行之前发生。
我该怎么做呢?问题的根本原因是什么?
答案 0 :(得分:7)
显然终结器线程正在最终确定已经处理好的SafeHandle。这是AesCryptoServiceProvider.Dispose(bool)方法的实现:
protected override void Dispose(bool disposing)
{
try {
if (disposing) {
if (this.m_key != null) this.m_key.Dispose();
if (this.m_cspHandle != null) this.m_cspHandle.Dispose();
}
}
finally {
base.Dispose(disposing);
}
}
三个错误:
所有三个错误的组合足以触发此MDA。它仍然在.NET 4.0中被窃听,但至少GC.SuppressFinalize由SymmetricAlgorithm.Dispose(bool)调用,因此不会使用终结器。
鼓励看到框架大师搞砸了。您可以在connect.microsoft.com上报告问题。要阻止调试器唠叨这一点,请使用Debug + Exceptions,Managed Debugging Assistants,取消ReleaseHandleFailed。默认情况下,这个是未被攻击的,这肯定是你第一个注意到这个错误的原因。
我认为第三个错误使这成为一个关键问题btw,从技术上讲,这个bug可能会导致回收句柄值被关闭。虽然赔率非常小。相当具有讽刺意味,因为这是一个安全的手柄类。