Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I leaking memory in a loop?

I'm a new programmer and I just come up with a question of memory leakage. Am I leaking memory if I declare a variable in a loop to make it be declared again and again? For example, I have

while(true)
{
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768);
    //do something else
}

I know it's an infinite loop but my question is about the memory. Is the memory usage growing fast in this loop? Should I release MyImage manually?

like image 992
YankeeWhiskey Avatar asked Dec 16 '22 23:12

YankeeWhiskey


2 Answers

You need to call MyImage.Dispose() after using it.

Another way is to change the code to:

while(true)
{
    using(Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)){
        //do something else
    }
}
like image 161
Ivo Avatar answered Dec 29 '22 21:12

Ivo


The Garbage Collector (GC) will do this work for you - eventually. In cases like you propose, you must be careful, as the GC in this case will try and manage the time it spends doing garbage collection vs. the applications memory consumption (the working set). Consequently application can consume more memory than it needs especially in cases like you illustrate.

The CLR handles this memory entirely automatically and you never deallocate managed memory yourself. For example consider the following

public void Test()
{
    byte[] myArray = new Byte[1000];
    // ...
}

when Test executes, an array to hold 1000 bytes is allocated on the memory heap. The array is reference by the variable myArray, stored on the local variable stack. When this method exits, this local variable pops out of scope, meaning that nothing is left to reference the array on the memory heap. The orphaned array then becomes eligible to be reclaimed by the GC. However, this collection may not happen immediately as the CLRs decision on whether to collect is based on a number of factors (available memory, the current allocation of memory, the time since last collection etc.) tThis means that there is an indeterminate delay on the time taken before garbage collection.

In light of the above, in the case you describe, you will get a vast increase in memory consumption for the duration of the loop/containing method. here it is much better to either use a using statement

while (true)
{
    using (Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768))
    {
        // ...
    }
}

or by calling dispose() on the Image object after each loop.

while (true)
{
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768);
    // ...
    MyImage.Dispose();
}

Asside: you can always check such memory consumption out for yourself (testing your processes real memory consumption) by querying a performance counter (using System.Diagnostics):

string procName = Process.GetCurrentProcess().ProcessName;
using (PerformanceCounter pc = new PerformanceCounter("Process", "Private Bytes", procName))
    Console.WriteLine(pc.NextValue());

Note: Reading performance counter requires administrator privileges.

like image 24
MoonKnight Avatar answered Dec 29 '22 20:12

MoonKnight