Mub*_*har 5 c# memory-leaks cryptography .net-3.5
任何人都可以确定以下代码中是否存在任何可能的内存泄漏.我曾尝试使用.Net Memory Profiler,它说"CreateEncryptor"和其他一些函数正在留下非托管内存泄漏,因为我已经使用性能监视器确认了这一点.
但是已经有处置,清晰,近距离通话,请相应地告诉我.这是一个迫切的问题.
public static string Encrypt(string plainText, string key)
{
//Set up the encryption objects
byte[] encryptedBytes = null;
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(key)))
{
byte[] sourceBytes = Encoding.UTF8.GetBytes(plainText);
using (ICryptoTransform ictE = acsp.CreateEncryptor())
{
//Set up stream to contain the encryption
using (MemoryStream msS = new MemoryStream())
{
//Perform the encrpytion, storing output into the stream
using (CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write))
{
csS.Write(sourceBytes, 0, sourceBytes.Length);
csS.FlushFinalBlock();
//sourceBytes are now encrypted as an array of secure bytes
encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer
csS.Close();
}
msS.Close();
}
}
acsp.Clear();
}
//return the encrypted bytes as a BASE64 encoded string
return Convert.ToBase64String(encryptedBytes);
}
private static AesCryptoServiceProvider GetProvider(byte[] key)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 256;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.GenerateIV();
result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] RealKey = GetKey(key, result);
result.Key = RealKey;
// result.IV = RealKey;
return result;
}
private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
{
byte[] kRaw = suggestedKey;
List<byte> kList = new List<byte>();
for (int i = 0; i < p.LegalKeySizes[0].MaxSize; i += 8)
{
kList.Add(kRaw[(i / 8) % kRaw.Length]);
}
byte[] k = kList.ToArray();
return k;
}
Run Code Online (Sandbox Code Playgroud)
更新:经过一些调查后,我将此记录为Microsoft connect上的错误.他们已经承认了这个bug并创建了一个修补程序.(显然,这是一个修补程序,因此通常的免责声明适用.如果可以,升级到.net 4.0可能是首选解决方案)
似乎这个代码在.net 3.5中泄漏,但在.net 4.0中运行良好.
我开始使用.net 4.0并将您的代码复制到一个快速测试应用程序中并将其称为1,000,000次,并且内存使用率始终保持在22.4mb.我还跟踪了GC堆大小和处理计数,它们都保持不变.据我所知,代码没有泄漏.
然后我在.net 3.5下重建了应用程序并重新运行测试,我得到了你所描述的确切泄漏.它起始于24mb左右,当它拨打100k电话时,内存使用量翻了一番,达到50mb以上.有趣的是,似乎Gen2堆正在增加,这表明它是一个托管内存泄漏而不是非托管句柄/内存.
如果可能我建议你尝试切换到.net 4.0.
我的完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
String encryptedString;
for (int j = 0; j < 1000; j++)
{
for (int i = 0; i < 1000; i++)
{
encryptedString = Encrypt(String.Format("test string {0} {1}", j, i), "key");
}
Console.WriteLine("j = {0}", j);
}
Console.WriteLine("Finished");
Console.ReadLine();
}
public static string Encrypt(string plainText, string key)
{
//Set up the encryption objects
byte[] encryptedBytes = null;
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(key)))
{
byte[] sourceBytes = Encoding.UTF8.GetBytes(plainText);
using (ICryptoTransform ictE = acsp.CreateEncryptor())
{
//Set up stream to contain the encryption
using (MemoryStream msS = new MemoryStream())
{
//Perform the encrpytion, storing output into the stream
using (CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write))
{
csS.Write(sourceBytes, 0, sourceBytes.Length);
csS.FlushFinalBlock();
//sourceBytes are now encrypted as an array of secure bytes
encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer
csS.Close();
}
msS.Close();
}
}
acsp.Clear();
}
//return the encrypted bytes as a BASE64 encoded string
return Convert.ToBase64String(encryptedBytes);
}
private static AesCryptoServiceProvider GetProvider(byte[] key)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 256;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.GenerateIV();
result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] RealKey = GetKey(key, result);
result.Key = RealKey;
// result.IV = RealKey;
return result;
}
private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
{
byte[] kRaw = suggestedKey;
List<byte> kList = new List<byte>();
for (int i = 0; i < p.LegalKeySizes[0].MaxSize; i += 8)
{
kList.Add(kRaw[(i / 8) % kRaw.Length]);
}
byte[] k = kList.ToArray();
return k;
}
}
}
Run Code Online (Sandbox Code Playgroud)