仍然是一个 "Multiple Dispose" 问题,尽管已得到处理
Still A "Multiple Dispose" Issue, Even Though Handled
在我的一些项目中,我一直在使用一对经过验证的数据encryption/decryption方法(加密方法粘贴在下面)。但我一直被这个关于 memoryStream 对象的烦人的 CA2202 警告 ("Do not dispose objects multiple times") 所困扰。我相信我以适当的方式处理了这个问题,但是每当我 运行 在 Visual Studio 中进行分析时,我仍然会收到警告。它从来没有在生产代码中抛出异常,但我仍然想一劳永逸地摆脱警告。那可能吗?还是我应该忽略它?提前致谢。
public static string Encrypt(string clearText, string passPhrase, string saltValue)
{
byte[] clearTextBytes = Encoding.UTF8.GetBytes(clearText);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(saltValue);
Rfc2898DeriveBytes passPhraseDerviedBytes = new Rfc2898DeriveBytes(passPhrase, saltValueBytes);
byte[] keyBytes = passPhraseDerviedBytes.GetBytes(32);
byte[] initVectorBytes = passPhraseDerviedBytes.GetBytes(16);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
byte[] cipherTextBytes = null;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(clearTextBytes, 0, clearTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
}
}
finally
{
if (memoryStream != null)
{
memoryStream.Dispose();
}
}
return Convert.ToBase64String(cipherTextBytes);
}
因为CryptoStream
关闭了memoryStream
您正在使用构造函数
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
: this(stream, transform, mode, false) {
}
调用
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen) {
_stream = stream;
_leaveOpen = leaveOpen;
//...
}
_leaveOpen
和_stream
后来用在Dispose
protected override void Dispose(bool disposing) {
try {
if (!_leaveOpen) {
_stream.Close();
}
//...
}
}
您可以删除 memoryStream.Dispose();
,或将 true
作为参数传递给 CryptoStream
构造函数
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write, true)) { }
问题是对 CryptoStream.Dispose
的调用可以 调用给定流上的处置:
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (!_finalBlockTransformed)
{
FlushFinalBlock();
}
if (!_leaveOpen)
{
_stream.Close();
}
}
}
...
}
如果你使用带4个参数的构造函数:
CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen)
最后一个参数决定流是否关闭。依次调用 Close()
,默认情况下还会调用 Dispose
:
public virtual void Close()
{
/* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully.
Contract.Ensures(CanRead == false);
Contract.Ensures(CanWrite == false);
Contract.Ensures(CanSeek == false);
*/
Dispose(true);
GC.SuppressFinalize(this);
}
因此,检查似乎无法正确确定具体的 Stream 实现是否会被 Disposed,而回过头来认为它会被处理 - 就是这种情况。
但是请注意,在大多数情况下,处理两次、一次或零次 MemoryStream
并不重要。
在我的一些项目中,我一直在使用一对经过验证的数据encryption/decryption方法(加密方法粘贴在下面)。但我一直被这个关于 memoryStream 对象的烦人的 CA2202 警告 ("Do not dispose objects multiple times") 所困扰。我相信我以适当的方式处理了这个问题,但是每当我 运行 在 Visual Studio 中进行分析时,我仍然会收到警告。它从来没有在生产代码中抛出异常,但我仍然想一劳永逸地摆脱警告。那可能吗?还是我应该忽略它?提前致谢。
public static string Encrypt(string clearText, string passPhrase, string saltValue)
{
byte[] clearTextBytes = Encoding.UTF8.GetBytes(clearText);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(saltValue);
Rfc2898DeriveBytes passPhraseDerviedBytes = new Rfc2898DeriveBytes(passPhrase, saltValueBytes);
byte[] keyBytes = passPhraseDerviedBytes.GetBytes(32);
byte[] initVectorBytes = passPhraseDerviedBytes.GetBytes(16);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
byte[] cipherTextBytes = null;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(clearTextBytes, 0, clearTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
}
}
finally
{
if (memoryStream != null)
{
memoryStream.Dispose();
}
}
return Convert.ToBase64String(cipherTextBytes);
}
因为CryptoStream
关闭了memoryStream
您正在使用构造函数
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
: this(stream, transform, mode, false) {
}
调用
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen) {
_stream = stream;
_leaveOpen = leaveOpen;
//...
}
_leaveOpen
和_stream
后来用在Dispose
protected override void Dispose(bool disposing) {
try {
if (!_leaveOpen) {
_stream.Close();
}
//...
}
}
您可以删除 memoryStream.Dispose();
,或将 true
作为参数传递给 CryptoStream
构造函数
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write, true)) { }
问题是对 CryptoStream.Dispose
的调用可以 调用给定流上的处置:
protected override void Dispose(bool disposing) { try { if (disposing) { if (!_finalBlockTransformed) { FlushFinalBlock(); } if (!_leaveOpen) { _stream.Close(); } } } ... }
如果你使用带4个参数的构造函数:
CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen)
最后一个参数决定流是否关闭。依次调用 Close()
,默认情况下还会调用 Dispose
:
public virtual void Close() { /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully. Contract.Ensures(CanRead == false); Contract.Ensures(CanWrite == false); Contract.Ensures(CanSeek == false); */ Dispose(true); GC.SuppressFinalize(this); }
因此,检查似乎无法正确确定具体的 Stream 实现是否会被 Disposed,而回过头来认为它会被处理 - 就是这种情况。
但是请注意,在大多数情况下,处理两次、一次或零次 MemoryStream
并不重要。