C# 获得;ReleaseHandleFailed“;使用加密后终结器线程中的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))

在循环中第二次运行此代码后,我得到了一个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))
{
    // ... 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);
    }
}