My application keeps growing in size everytime I open and close a certain Form. I used dotTrace and came up with an ever growing list of object of type System.Drawing.Internal.GPStream which are creating byte arrays continuously without every disposing them. I did some research and found out the .net does not support any means of closing such memory streams. the following
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (t.IsClass && t.BaseType.Name.ToLower() == "form")
{
//Assembly ass = Assembly.GetExecutingAssembly();
object obj = null;
obj = Activator.CreateInstance(t);
Form f = new Form();
f = (Form)obj;
if ((string)f.Tag != "DNI") // Do Not Import
{
DataRow dr = Formsdt.NewRow();
dr["Name"] = f.Name;
dr["Text"] = f.Text;
dr["Tag"] = f.Tag;
Formsdt.Rows.Add(dr);
}
}
}
The intent of this code is to loop over all Forms and retrieve the controls in order to set access rights to users, activating and deactivating controls as needed programmatically.
Any insight is appreciated.
Note that
While( i am opening and closing the form)
==> Memory Allocation keeps on increasing
Somethings not being disposed of properly. Do you have warnings that say X class is iDisposable and you're not disposing it? Look into using 'using' blocks.
See this :
"A FileStream involves unmanaged resources which could actually be
immediately freed upon calling Dispose. A MemoryStream, on the other
hand, stores a managed byte array in its _buffer variable, which is
not freed at disposal time. In fact, the _buffer is not even nulled in
the MemoryStream's Dispose method, which is a SHAMEFUL BUG IMO because
nulling the reference could make the memory eligible for GC right at
disposal time. Instead, a lingering (but disposed) MemoryStream
reference still holds onto memory. Therefore, once you dispose it, you
should also null it if it's still in scope." – Triynko Oct 25 '10 at
20:46
Is a memory leak created if a MemoryStream in .NET is not closed?
Creating Forms in a loop will cause problems, depending the code in it's constructor it can fire events that will choke the message loop. Just to check, try adding an application.doevents in the loop and watch if memory gets released.
Maybe you will need to refactor your classes in order to determine access on a property that is outside a form. Something like:
Class MyObject
Public my_form as Form
Public Tag as string
end class
So you don't need to instantiate a Form.
Regards,
MarianoC.
Related
Edit: Please just take into consideration the sample I provided. There are no events being called. The code I provided is all that there is. I just want to know of global objects in a form must be manually de-allocated. It would be nice to also know why a form going out of scope doesn't get cleaned up, but that is secondary.
Closing or calling dispose on a Form does not seem to deallocate that form's global objects. I have a form that will be instantiated multiple times and after opening a number of times I am getting an OutOfMemory exception, even if all the previous forms were closed. I can get memory to free by making every object I am using disposable, but I thought in general the garbage collection took care of cleaning up objects out of scope.
Here is a simple example of a form with just a multidimensional double array:
using System;
using System.Windows.Forms;
namespace surGroupTool
{
public partial class TestForm : Form
{
double[,] testArray;
public TestForm()
{
InitializeComponent();
testArray = new double[5000, 5000];
}
}
}
When I create the form in an infinite loop it quickly runs out of memory, even if I dispose and set it to null.
while (true)
{
TestForm testForm = new TestForm();
testForm.Dispose();
testForm = null;
}
Must every object be manually disposed for a closed/disposed form?
I was unable to reproduce the issue with the given source code. This screenshot is from about 20 seconds. But I left it running while getting coffee and it was still fine. It was looping the memory pattern as shown above.
One thing I noticed is that it takes some time before the GC frees up memory. The GC only runs when your starting to get low on memory or when manually calling it with GC.Collect();. At that point a background process will start that does the actual cleaning. This garbage collection thread does not fully interrupt your programs main thread (according to the Microsoft documentation > background workstation garbage collection). So this means that it is possible to keep allocating memory even when the GC is running. At that point it is a race who's first. You in allocating enough memory to get out of bounds. or your GC with its cleanup.
Must every object be manually disposed for a closed/disposed form?
No, generally global resources do not have to be disposed. The GC will clean them up if nothing is referencing them. However if a global resources is an unmanaged resources (like a stream or a bitmap) you need to dispose it before it can be cleaned, this is the same for local unmanaged resource.
from the comments:
This happens even if each form is created by a user clicking a button...with minutes between forms being created.
I'm going to assume that this is in your real application and not with the form provided as a test sample. You are most likely leaving a reference to that form (for example via a dialog result, or open undamaged resource). If it is with the given form I cannot explain it and you might need to check if you haven't overwritten the GC settings to something very exotic, or disabled it all together.
I have a groupbox named "radGroupBox1" that I want to open a user control in that.
This is my code:
radGroupBox1.Controls.Clear();
_main2 = new Forms.MainControl2();
radGroupBox1.Controls.Add(_main2);
_main2.Dock = DockStyle.Fill;
_main2.Frm = this;
_main2.Show();
My problem is every time I execute this code , My memory increase. I check it in task manager. For example if you click 10 times on my button(run code) , Memory will increase 10 time. How can i release Memory allocated to previous object ?
Is there any way to Dispose it or force GC to release memory?
As you can read in the documentation:
Calling the Clear method does not remove control handles from memory. You must explicitly call the Dispose method to avoid memory leaks.
So this means that you have to Dispose the user control yourself. Also, be sure that inside the user-control you are disposing any disposable resources.
radGroupBox1.Controls.Clear();
_main2?.Dispose();
_main2 = new Forms.MainControl2();
radGroupBox1.Controls.Add(_main2);
_main2.Dock = DockStyle.Fill;
_main2.Frm = this;
_main2.Show();
I'm noticing a lot of byte[] getting stuck in memory when profiling my program. I did some digging and found the majority of the instances created in some manner like this:
public byte[] CreateBytes(byte[] bytes)
{
using (var start = new MemoryStream())
{
using (var memStr = new MemoryStream(bytes))
{
//do stuff
return start.ToArray();
}
}
}
The returned byte[] is then passed to other methods and is used in creating another MemoryStream from within another using block:
using (var uncompressedStream = new MemoryStream(uncompressedData))
{
using (var compressedStream = new MemoryStream())
{
//Do some compression
}
}
myObject.Bytes = uncompressedData;
uncompressedData = null;
return myObject;
(uncompressedData is the value returned from CreateBytes()).
My question is, when does the byte[] get cleaned up? Do I specifically need to set it to null, and if so, where? After the second using block I no longer need it, but if I simply put uncompressedData = null; I'm not sure that's going to reclaim the memory.
I would've thought that the using statement in CreateBytes(byte[] bytes) would've disposed of the bytes, but since it's returning a reference does that postpone and/or forego the disposal?
EDIT: I added another line of code. Since I'm storing the uncompressedBtyes in another object, setting uncompressedData to null is pointless and the byte[] will live as long as myObject (or until myObject.Bytes is set to null), correct?
The byte[] gets cleaned up when two conditions are both satisfied:
There are no references to that memory block
The garbage collector decides to collect that memory block
The GC runs at non-deterministic times based on a variety of factors.
The byte array, just like any other managed object in memory, is eligible for garbage collection as soon as it is no longer accessible from any root reference. You can trust the GC to know when that's happened, and to intelligently schedule times to actually do the clean up of eligible objects. Try not to worry about when an object that's eligible for cleanup is actually cleaned up, chances are the GC knows better than you.
In addition to Erics answer:
When you are sure you do not more need that byte[], assign to it null.
This will not guarantee that memory will be reclaimed now, neither that it will be reclimed after, this is just a way to help GC to identify it like a subject for collection.
The using statement really has nothing to do with the byte array you are returning.
The MemoryStream is disposable, and disposal of that object is what the using statement is managing (note that disposal is not the same as garbage collection, but is typically a precursor thereto).
When you call ToArray(), you are creating something new that is not disposable; once it is out of scope, it will be cleaned up by the garbage collector at an indeterminate time (this is typically a well optimized process).
How could be defined a code that store 'this' during class finalization? How the garbage collector should behave (if defined somewhere)?
In my mind the GC should finalize multiple times the class instance, and the following test application shall print "66", but the finalizer is executed only once, causing the application to print "6".
Few lines of code:
using System;
namespace Test
{
class Finalized
{
~Finalized()
{
Program.mFinalized = this;
}
public int X = 5;
}
class Program
{
public static Finalized mFinalized = null;
static void Main(string[] args)
{
Finalized asd = new Finalized();
asd.X = 6;
asd = null;
GC.Collect();
if (mFinalized != null)
Console.Write("{0}", mFinalized.X);
mFinalized = null;
GC.Collect();
if (mFinalized != null)
Console.Write("{0}", mFinalized.X);
}
}
}
What I'm trying to do is to understand how finalizers manage instance memory. In my application could be desiderable to re-use instance reference again for further processing.
It's clear that the finalizer doesn't "free" memory (at least in my test application). May the memory chunk be reused for other purposes? Or even freed? And if it isn't, that would be a memory leak or what?
Now, I'm confused more than before.
This is due to Resurrection. By storing the object in another variable during finalization (assigning this to a variable), you resurrect the obejct instance as far as the GC is concerned. You are allowed to resurrect your object in .NET, and you can actually cause the GC to finalize the object more than once, but you have to explicitly request it via GC.ReRegisterForFinalize .
For details, see Automatic Memory Management in the Microsoft .NET Framework.
GC.Collect does a sweep, special-casing any objects with a finalizer and not collecting them. Once these finalizer objects have finalized, GC then runs again over these objects. If they're no longer eligible for collection (by re-rooting, as you do), so be it. Normally the finalizer only runs once, but IIRC, you can request that it runs again.
Finalizer only gets called once. You're free to assign self to somewhere, and prevent the object being garbage collected. But once the object is available again for GC, it doesn't run the finalizer.
I'm interested in any good uses of resurrected objects.
The MSDN states "There are very few good uses of resurrection, and you really should avoid it if possible".
Also Bill Wagner in his Effective C# says "You cannot make this kind of construct work reliably. Dont try". But the book is 2 years old so maybe something changed?
On timer tick I am allocating new ClearCase ApplicationClass object, Is following code okay?
Or Do I need to release memory, If yes, How? I am using ClearCase Interop of ccauto.dll, I believe ccauto.dll is unmanaged code, I am confused, am I supposed to release the memory or not?
Please advise.
private void timer1_Tick(object sender, EventArgs e)
{
try
{
IClearCase ccNew = new ApplicationClass();
CCVOB vob = ccNew.get_VOB(ClearCaseVOB);
ccNew = null;
}
catch
{
}
}
2 comments:
according to "About CAL3" article:
Once you "GET" a ClearCase.Application object programmatically, do you need to keep getting the object in CAL?
Once the ClearCase.Application object is obtained, it can be used to get other objects
without having to create them again.
CAL ensures as best it can that CAL objects stay synchronized with the underlying ClearCase data, refreshing as necessary when invoking properties and methods.
However, the CAL objects can become invalid if someone deletes the underlying ClearCase data while a reference is still held by the CAL object.
Meaning: you could set a CCVOB instance once and for all (unless you think the Vob will disappear... which should be a very rare event!)
In C#, placing code in a using block ensures that the objects are disposed (though not necessarily collected) as soon as control leaves the block.
I am not sure if CCVOB implements Disposable, but if it does, setting it to null explicitly would prevent it to be properly disposed.
So I would not recommend ccNew = null;