I found a strange memory leak in my application and I don't know why it is happening but it drives me crazy. See the example below:
class Program
{
static void Main(string[] args)
{
var dataBuilder = new Program();
var dataBuilderWeakReference = new WeakReference(dataBuilder);
/* tons of data being processed */
dataBuilder = null;
GC.Collect();
GC.WaitForPendingFinalizers();
if(dataBuilderWeakReference.IsAlive)
{
throw new Exception("Why?");
}
}
}
This should work, am I right? The real problem is that the code runs inside a loop and it ends up with OOM exception:
class Program
{
static void Main(string[] args)
{
var dataBuilder = new Program();
var dataBuilderWeakReference = new WeakReference(dataBuilder);
while(true /* until there are some data */)
{
/* add record to data builder (tons of data) */
if(true /* data builder is full? */)
{
// create new data builder to save data into it
dataBuilder = null;
GC.Collect();
GC.WaitForPendingFinalizers();
if(dataBuilderWeakReference.IsAlive)
{
throw new Exception("Why?");
}
dataBuilder = new Program();
}
}
}
}
I tried profiling the code but the profiler tells me it's held by the main function.
In the example Program class doesn't have any member (for the sake of simplicity), but in the real application it holds references to tons of small (managed) objects and that's where I end up with OOM exception.
Thank you for any kind of help.
Aram Kocharyan suggested running code without 'Prefer 32-bit' option. Shocking result is, that my exception is not thrown i.e. memory is released as expected. BTW: My system is Windows 7 Professional, .NET 4.5, everything up to date.
Sadly my real application uses some mixed assemblies and has to be compiled as X86, thus 'Prefer 32-bit' option is not allowed for me.
OK, I did some tests and my application works if I launch the release build outside Visual Studio. I can see in Task Manager that memory is released as expected. However, It's a mystery to me, why GC behaves so differently in Debug or when Visual Studio is attached. I would expect some problems in release because of some optimizations, but not in debug. Maybe the debugger keeps references to objects longer.
There has to be some logical explanation for this.