3

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

Xaruth
  • 4,034
  • 3
  • 19
  • 26
Cogent
  • 404
  • 7
  • 16
  • Instead of looking for a leak in .NET, check the form for any GDI objects (eg Bitmaps) you are loading without disposing, or streams you are creating without closing them. Check [this](http://stackoverflow.com/questions/336387/image-save-throws-a-gdi-exception-because-the-memory-stream-is-closed) similar question – Panagiotis Kanavos Mar 14 '14 at 12:38
  • No streams or bitmaps are being explicitly being created. I do, however, the memory leak is indeed composed of byte[] which are consistent with memory leaks. – Cogent Mar 14 '14 at 13:02
  • I may add that i am absolutely certain that it is a memory IO stream driven problem. – Cogent Mar 14 '14 at 13:07
  • A memory stream typically used to load Bitmaps, defined in System.Drawing. You really need to check the form, it's not likely that you are the first to notice a leak in System.Drawing after 12 years. Does the form use Bitmaps or other GDI objects? – Panagiotis Kanavos Mar 14 '14 at 13:09
  • Maybe try Resharper, to find resources that aren't released. – Max Mar 14 '14 at 14:56
  • Use a memory profiler. THere are some on the market and at least memprofiler has a 7 day free trial. Then you KNOW. – TomTom Mar 18 '14 at 14:31
  • I've come out empty handed thus far. I did add a using statement to the line that is raising this memory issue: using (Form f = (Form)Activator.CreateInstance(t)) still same results. I understand that Activator will create duplicates of objects regardless how many times it has been called, and i have implemented Idisposable to clear datasets and global variables. Still no luck. – Cogent Mar 20 '14 at 09:27

2 Answers2

1

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?

Community
  • 1
  • 1
C4F
  • 662
  • 7
  • 18
  • 1
    For example from the code posted the op does `Form f = new Form();` (which he should not even do) which does not get disposed. Also he does `f = (Form)obj` and never disposed that object either. (You really should be just doing `using(Form f = (Form)obj)` – Scott Chamberlain Mar 14 '14 at 12:51
  • I have tried the using block, but still no success. Anyway i have reason to believe that the activator is causing this problem, but can't be certain yet. All i know for sure is that System.Drawing.Internal.GPStream is the cause of my problems at this point. All attempts to solve the memory leak issue failed. I did use the code suggested by @ScottChamberlain , it changed nothing, since forms are of type Idisposable and are freed up by GC, unlike memory streams. – Cogent Mar 14 '14 at 12:57
  • All [Stream](http://msdn.microsoft.com/en-us/library/system.io.stream(v=vs.110).aspx) derived objects *are* disposable. MemoryStream is such a class. You are talking about a different stream object – Panagiotis Kanavos Mar 14 '14 at 13:11
  • @Cogent The problem is not in the code you showed, the problem is in the code of one of the Form objects you create. I only used your code as an example of what you needed to do, you will need to go though each Form and find the one that is not disposing of it's own objects correctly. – Scott Chamberlain Mar 14 '14 at 13:33
  • @Cogent If whatever idisposable you're creating is large enough you should see the memory spike up when you allocate it. Perhaps load an enormously large one and see if it drops when you close the form? Should help you pinpoint your debugging if you're not getting informative warnings. – C4F Mar 14 '14 at 14:24
  • When the application opens this particular form RAM usage increases by 3.25 MB, upon closing it, the usage doesn't drop whatsoever. Every dataset is beign explicitly disposed of just to make sure. Other forms are behaving normally. – Cogent Mar 14 '14 at 20:23
  • What are you doing with the DataRow? Are you using a DataContext somewhere? You have to be careful, they cause leaks via cache use – C4F Mar 14 '14 at 20:37
  • I have used CLR profiler, and it gave me the same result. The leak is caused by a MemoryStream (Byte[]) which is occupying roughly 14 MB in total of memory. Caller is indeed Internal.GPStream Handle, and there's quite nothing i can do about it. – Cogent Mar 18 '14 at 08:09
  • @Cogent See my edited answer, it contains info about your MemoryStream not being released upon dispose. Apparently, it also needs to be nulled to immediately release memory. – C4F Mar 18 '14 at 14:30
0

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.

MarianoC
  • 341
  • 3
  • 3