C# 数组c的内存泄漏#
用户指定文件名和块大小。原始文件拆分为具有用户块大小的块(最后一个块除外)。对于每个块,计算哈希函数SHA256并写入控制台 这是一个有2个线程的程序:第一个线程读取原始文件并放入块的队列字节数组中;第二个线程从队列中删除块的字节数组并计算哈希 在第一次迭代之后,直到程序完成,内存才会被释放。C# 数组c的内存泄漏#,c#,arrays,multithreading,out-of-memory,C#,Arrays,Multithreading,Out Of Memory,用户指定文件名和块大小。原始文件拆分为具有用户块大小的块(最后一个块除外)。对于每个块,计算哈希函数SHA256并写入控制台 这是一个有2个线程的程序:第一个线程读取原始文件并放入块的队列字节数组中;第二个线程从队列中删除块的字节数组并计算哈希 在第一次迭代之后,直到程序完成,内存才会被释放。 在下一次迭代中,内存正常分配和处理。 所以,在下一次读取part数组时,我得到了OutOfMemoryException 如何正确管理内存以避免内存泄漏 class Encryption { st
在下一次迭代中,内存正常分配和处理。
所以,在下一次读取part数组时,我得到了
OutOfMemoryException
如何正确管理内存以避免内存泄漏
class Encryption
{
static FileInfo originalFile;
static long partSize = 0;
static long lastPartSize = 0;
static long numParts = 0;
static int lastPartNumber = 0;
static string[] hash;
static Queue<byte[]> partQueue = new Queue<byte[]>();
public Encryption(string _filename, long _partSize)
{
try
{
originalFile = new FileInfo(@_filename);
partSize = _partSize;
numParts = originalFile.Length / partSize;
lastPartSize = originalFile.Length % partSize;
if (lastPartSize != 0)
{
numParts++;
}
else if (lastPartSize == 0)
{
lastPartSize = partSize;
}
lastPartNumber = (int)numParts - 1;
hash = new string[numParts];
}
catch (FileNotFoundException fe)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
return;
}
catch (Exception e)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
}
}
private void readFromFile()
{
try
{
using (FileStream fs = new FileStream(originalFile.FullName, FileMode.Open, FileAccess.Read))
{
for (int i = 0; i < numParts; i++)
{
long len = 0;
if (i == lastPartNumber)
{
len = lastPartSize;
}
else
{
len = partSize;
}
byte[] part = new byte[len];
fs.Read(part, 0, (int)len);
partQueue.Enqueue(part);
part = null;
}
}
}
catch(Exception e)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
}
}
private static void hashToArray()
{
try
{
SHA256Managed sha256HashString = new SHA256Managed();
int numPart = 0;
while (numPart < numParts)
{
long len = 0;
if (numPart == lastPartNumber)
{
len = lastPartSize;
}
else
{
len = partSize;
}
hash[numPart] = sha256HashString.ComputeHash(partQueue.Dequeue()).ToString();
numPart++;
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
}
}
private void hashWrite()
{
try
{
Console.WriteLine("\nResult:\n");
for (int i = 0; i < numParts; i++)
{
Console.WriteLine("{0} : {1}", i, hash[i]);
}
}
catch(Exception e)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
}
}
public void threadsControl()
{
try
{
Thread readingThread = new Thread(readFromFile);
Thread calculateThread = new Thread(hashToArray);
readingThread.Start();
calculateThread.Start();
readingThread.Join();
calculateThread.Join();
hashWrite();
}
catch (Exception e)
{
Console.WriteLine("Error: {0}\nStackTrace: {1}", fe.Message, fe.StackTrace);
}
}
}
类加密
{
静态文件信息原始文件;
静态长零件尺寸=0;
静态长lastPartSize=0;
静态长numParts=0;
静态int lastPartNumber=0;
静态字符串[]散列;
静态队列partQueue=新队列();
公共加密(字符串\u文件名,长\u部分大小)
{
尝试
{
originalFile=新文件信息(@_文件名);
零件尺寸=_零件尺寸;
numParts=原始文件长度/零件尺寸;
lastPartSize=原始文件。长度%partSize;
如果(lastPartSize!=0)
{
numParts++;
}
else if(lastPartSize==0)
{
lastPartSize=零件尺寸;
}
lastPartNumber=(int)numParts-1;
哈希=新字符串[numParts];
}
捕获(FileNotFoundException fe)
{
WriteLine(“错误:{0}\n堆栈跟踪:{1}”,fe.Message,fe.StackTrace);
回来
}
捕获(例外e)
{
WriteLine(“错误:{0}\n堆栈跟踪:{1}”,fe.Message,fe.StackTrace);
}
}
私有void readFromFile()
{
尝试
{
使用(FileStream fs=newfilestream(originalFile.FullName,FileMode.Open,FileAccess.Read))
{
对于(int i=0;i
在编写此类代码之前,您应该阅读一些有关.NET内部结构的书籍。你对.NET内存模型的理解是完全错误的,这就是为什么你会犯这样的错误<如果您关心您的资源,尤其是在处理数组时,代码>OutOfMemoryException很少发生
您应该知道,在.NET运行时中,引用对象有两个堆,基本堆和堆,它们之间最重要的区别是LOH即使在垃圾收集之后也不会被压缩
您应该知道,所有的阵列,即使是小的阵列,都将进入LOH,并且内存消耗非常快。您还应该知道,这一行:
part = null;
马上。更糟的是,这行根本不做任何事情,因为您仍然有一个引用您在队列中读取的文件的部分。这就是你的记忆力衰退的原因。您可以尝试在每次散列计算后调用GC
来解决此问题,但这是强烈建议的解决方案
您应该重写您的算法(这是非常简单的生产者/消费者
模式),而不必同时将整个文件内容存储在内存中。这非常简单-只需将部分
变量移出静态字段,并将下一个文件部分读入其中。在代码中引入(或)而不是队列,并在读取文件的下一部分后立即计算下一个散列
我记录