C# 获得;ReleaseHandleFailed“;使用加密后终结器线程中的MDA
在循环中第二次运行此代码后,我得到了一个MDA(使用不同的C# 获得;ReleaseHandleFailed“;使用加密后终结器线程中的MDA,c#,cryptography,C#,Cryptography,在循环中第二次运行此代码后,我得到了一个MDA(使用不同的文件参数: 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))
文件参数:
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。)
stacktrace信息量不大:
mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Dispose(bool disposing)+0x10字节
mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Finalize()+0x1a字节
我怀疑其中一个流或CryptoServiceProvider由于某种原因没有被释放。除此之外,代码运行良好,并按预期执行。MDA发生在控件到达方法的第一行之前
如何正确执行此操作?问题的根本原因是什么?显然,终结器线程正在终结已释放的安全句柄。这是AESCryptServiceProvider.Dispose(bool)方法的实现:
三个错误:
- 在处理完m_key字段后,它不会将其设置为null
- 不调用GC.SuppressFinalize(),甚至不被.NET3.5中的基类调用
- SafeCapiKeyHandle类不会使其ReleaseHandle()方法中存储的句柄无效
这三个错误的组合足以触发此MDA。它在.NET 4.0中仍然存在错误,但Symmetrialgorithm.Dispose(bool)至少调用了GC.SuppressFinalize,因此不会使用终结器
看到框架主控程序出错令人振奋。您可以在connect.microsoft.com上报告问题。要阻止调试器对此进行唠叨,请使用Debug+异常、托管调试助手、untick ReleaseHandleFailed。默认情况下,此项是取消选中的,这肯定是您第一个注意到此错误的原因
我认为第三个错误使这成为一个关键问题。顺便说一句,从技术上讲,这个错误可能导致关闭回收的句柄值。尽管可能性很小。但很讽刺的是,考虑到这是一个安全的句柄类。您应该使用
语句删除嵌套的周围的大括号;这将使您的代码更短。Added stacktrace和重新格式化的代码。这是来自终结器线程。它来自于引发异常之前执行的某段代码。我在此期间进行了计算。我还发现:因此这不是一个真正的异常,而是一个MDA。故障排除提示根本没有帮助。我不访问和处理let是的,我勾选了一些复选框,因为出于某种原因,所有的异常都被关闭了,我不知道默认值。
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);
}
}