我是一名新程序员,我想出了一个内存泄漏问题。如果我在循环中声明一个变量以使其一次又一次地被声明,我是否会泄漏内存? 例如,我有
while(true)
{
Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768);
//do something else
}
我知道这是一个无限循环,但我的问题是关于记忆。此循环中的内存使用量是否快速增长?我应该手动发布MyImage吗?
答案 0 :(得分:6)
使用后需要致电MyImage.Dispose()
。
另一种方法是将代码更改为:
while(true)
{
using(Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)){
//do something else
}
}
答案 1 :(得分:3)
垃圾收集器(GC)将为您完成这项工作 - 最终。在你提出的情况下,你必须要小心,因为在这种情况下,GC会尝试和管理垃圾收集所花费的时间与应用程序内存消耗(工作集)。因此,应用程序可能会消耗更多的内存,尤其是在您所说明的情况下。
CLR完全自动处理此内存,您永远不会自行释放托管内存。例如,请考虑以下
public void Test()
{
byte[] myArray = new Byte[1000];
// ...
}
当Test
执行时,在内存堆上分配一个容纳1000个字节的数组。该数组由变量myArray
引用,存储在本地变量堆栈中。当此方法退出时,此局部变量会超出范围,这意味着没有任何内容可以引用内存堆上的数组。然后孤立的阵列有资格被GC回收。但是,这个集合可能不会立即发生,因为CLR决定是否收集是基于多种因素(可用内存,当前内存分配,自上次收集后的时间等)t这意味着存在不确定的延迟垃圾收集前的时间。
鉴于上述情况,在您描述的情况下,在循环/包含方法的持续时间内,您将大大增加内存消耗。在这里使用using
语句
while (true)
{
using (Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768))
{
// ...
}
}
或在每次循环后在dispose()
对象上调用Image
。
while (true)
{
Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768);
// ...
MyImage.Dispose();
}
Asside:您可以通过查询性能计数器(使用System.Diagnostics)来自行检查此类内存消耗(测试您的进程实际内存消耗):
string procName = Process.GetCurrentProcess().ProcessName;
using (PerformanceCounter pc = new PerformanceCounter("Process", "Private Bytes", procName))
Console.WriteLine(pc.NextValue());
注意:阅读效果计数器需要管理员权限。
答案 2 :(得分:1)
如果我在循环中声明一个变量以便一次又一次地声明它,我是否会泄漏内存?
不,你没有,其他人提到的问题可能是Image正在包装一个Image对象
但是对于你的问题,在循环中声明一个变量并在每次迭代时为它赋予一个新值不是问题
答案 3 :(得分:1)
在某些情况下,紧密循环会导致OOM问题。但是,Image
实现了IDisposable
,因此请务必通过using
语句调用它,以便在完成后可以释放资源。
using (Image<Gray, Byte> MyImage = new Image<Gray, Byte>(1024, 768))
{
//do stuff
}
如果Image<T,U>
实现任何托管对象,请确保IDisposable
实现Image<T,U>
。
答案 4 :(得分:1)
在你的问题的一般形式中,你本身并没有泄漏内存,但是你可能比GC减少内存占用内存的速度更快(取决于你正在使用的对象的确切行为和内存占用) 。如果是这样,这会产生很多类似内存泄漏的效果。
在您的特定示例中,Image对象包含非托管资源,可能包括内存(或文件句柄或GDI对象等)。正如其他答案所指出的那样,如果您不进行处置,那么这些非托管资源将无法回收(或者如果他们有终结器,可以在GC的第二遍中回收)。