繁体   English   中英

对象“ iCrypt”可以被多次处置

[英]Object 'iCrypt' can be disposed more than once

我已经看到有关此问题的几个问题。 例如:

“对象可以被处置多次”错误

但是我不能完全确定我应该如何处理我的代码。 我从代码分析中得到的警告是:

1> D:\\ My Programs \\ 2017 \\ PTSTools \\ PTSTools \\ PTSTools.cs(81):警告CA2202:Microsoft。用法:对象'iCrypt'可以在方法'PTSToolsClass.Crypt(string,string,bool )”。 为避免生成System.ObjectDisposedException,不应在一个对象上调用Dispose多次。:行:81

有问题的方法:

private string Crypt(string strData, string strPassword, bool bEncrypt)
{
    byte[] u8Salt = new byte[] { ... };

    PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);

    Rijndael iAlg = Rijndael.Create();
    iAlg.Key = iPass.GetBytes(32);
    iAlg.IV = iPass.GetBytes(16);

    ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();

    MemoryStream iMem = new MemoryStream();
    CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write);

    byte[] u8Data;
    if (bEncrypt)
        u8Data = Encoding.Unicode.GetBytes(strData);
    else
        u8Data = Convert.FromBase64String(strData);

    try
    {
        iCrypt.Write(u8Data, 0, u8Data.Length);
        iCrypt.Close();
        if (bEncrypt)
            return Convert.ToBase64String(iMem.ToArray());
        else
            return Encoding.Unicode.GetString(iMem.ToArray());
    }
    catch
    {
        return null;
    }
    finally
    {
        iCrypt.Close();
    }
}

有人可以解释一下为什么我在finally的代码行中收到此警告吗?

谢谢。

更新:

根据评论,我将其更改为:

private string Crypt(string strData, string strPassword, bool bEncrypt)
{
    byte[] u8Salt = new byte[] { ... };

    PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);

    Rijndael iAlg = Rijndael.Create();
    iAlg.Key = iPass.GetBytes(32);
    iAlg.IV = iPass.GetBytes(16);

    ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();

    MemoryStream iMem = new MemoryStream();
    using (CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write))
    {
         byte[] u8Data;
        if (bEncrypt)
            u8Data = Encoding.Unicode.GetBytes(strData);
        else
            u8Data = Convert.FromBase64String(strData);

        try
        {
            iCrypt.Write(u8Data, 0, u8Data.Length);
            iCrypt.Close();
            if (bEncrypt)
                return Convert.ToBase64String(iMem.ToArray());
            else
                return Encoding.Unicode.GetString(iMem.ToArray());
        }
        catch
        {
            return null;
        }
    }
}

但是我现在有这些警告:

1>D:\My Programs\2017\PTSTools\PTSTools\PTSTools.cs(77): warning CA2202: Microsoft.Usage : Object 'iCrypt' can be disposed more than once in method 'PTSToolsClass.Crypt(string, string, bool)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 77
1>D:\My Programs\2017\PTSTools\PTSTools\PTSTools.cs(77): warning CA2202: Microsoft.Usage : Object 'iMem' can be disposed more than once in method 'PTSToolsClass.Crypt(string, string, bool)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 77

现在,它不喜欢catch块。

更新:

了解:

   private string Crypt(string strData, string strPassword, bool bEncrypt)
    {
        byte[] u8Salt = new byte[] { 0x26, 0x19, 0x81, 0x4E, 0xA0, 0x6D, 0x95, 0x34, 0x26, 0x75, 0x64, 0x05, 0xF6 };

        PasswordDeriveBytes iPass = new PasswordDeriveBytes(strPassword, u8Salt);

        Rijndael iAlg = Rijndael.Create();
        iAlg.Key = iPass.GetBytes(32);
        iAlg.IV = iPass.GetBytes(16);

        ICryptoTransform iTrans = (bEncrypt) ? iAlg.CreateEncryptor() : iAlg.CreateDecryptor();

        MemoryStream iMem = new MemoryStream();
        using (CryptoStream iCrypt = new CryptoStream(iMem, iTrans, CryptoStreamMode.Write))
        {
                byte[] u8Data;
            if (bEncrypt)
                u8Data = Encoding.Unicode.GetBytes(strData);
            else
                u8Data = Convert.FromBase64String(strData);

            try
            {
                iCrypt.Write(u8Data, 0, u8Data.Length);
                if (bEncrypt)
                    return Convert.ToBase64String(iMem.ToArray());
                else
                    return Encoding.Unicode.GetString(iMem.ToArray());
            }
            catch
            {
                return null;
            }
        }
    }

因为finally一个的块try-(catch-)finally块总是执行 ,分析器看到此:

try
{
    iCrypt.Close();
}
finally
{
    iCrypt.Close();
}

然后,它正确地推断出这些调用可以连续发生,从而导致ObjectDisposedException抛出在第二个调用中。

因此:您无需在try块中使用iCrypt.Close() ,因为无论是否发生异常,它将始终在finally关闭。

您正在调用iCrypt.Close(); 两次,从try语句中删除该调用,就可以了。

来自代码分析的消息很清楚。 您的代码两次处置(关闭)iCrypt。 在try块中一次,在finally块中一次。 删除行iCrypt.Close(); 在try块中(在iCrypt.Write(...)if(...) ,警告将消失。

更好的办法是使用块:

using (CryptoStream iCrypt = new CryptoStream(...)) {
   .... // your code without the finally block
}

无论是否在块内引发异常,使用方法都将调用iCrypt.Close()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM