|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
GC and disposeWhen I create an instance of one of my classes inside a method, does it make a difference if I call its Dispose method? public class Foo : IDisposable { public Foo { } public Foo anotherFoo = null; public void Dispose() { } } Given the class above is there a difference between the two examples below? When will the GC give back the memory? Does ExampleA confuse GC when it comes to tracking and releasing foo2? public void ExampleA() { Foo foo1 = new Foo(); Foo foo2 = new Foo(); Foo foo3 = new Foo(); foo1.anotherFoo = foo2; foo1.anotherFoo = foo3; } public void ExampleB() { Foo foo1 = new Foo(); Foo foo2 = new Foo(); Foo foo3 = new Foo(); foo1.anotherFoo = foo2; foo2.Dispose(); foo1.anotherFoo = foo3; foo1.Dispose(); foo3.Dispose(); } Thanx, -- Petros You example doesn't help because there's nothing in Foo that needs
disposing, and Dispose isn't related to GC as you seem to be assuming. -- Show quotePhil Wilson [MVP Windows Installer] ---- "Petros Amiridis" <pet***@nowhere.net> wrote in message news:%23shS3nIlGHA.1320@TK2MSFTNGP04.phx.gbl... > Hi, > > When I create an instance of one of my classes inside a method, does it > make a difference if I call its Dispose method? > > public class Foo : IDisposable > { > public Foo > { > } > > public Foo anotherFoo = null; > > public void Dispose() > { > } > } > > Given the class above is there a difference between the two examples > below? When will the GC give back the memory? Does ExampleA confuse GC > when it comes to tracking and releasing foo2? > > public void ExampleA() > { > Foo foo1 = new Foo(); > Foo foo2 = new Foo(); > Foo foo3 = new Foo(); > foo1.anotherFoo = foo2; > foo1.anotherFoo = foo3; > } > > public void ExampleB() > { > Foo foo1 = new Foo(); > Foo foo2 = new Foo(); > Foo foo3 = new Foo(); > foo1.anotherFoo = foo2; > foo2.Dispose(); > foo1.anotherFoo = foo3; > foo1.Dispose(); > foo3.Dispose(); > } > > Thanx, > > -- > Petros Phil Wilson wrote:
> You example doesn't help because there's nothing in Foo that needs What if it does have something that needs disposing? An if Dispose> disposing, and Dispose isn't related to GC as you seem to be assuming. doesn't have anything to do with GC, could tell me briefly what are good practices that can make your application consume less memory? I've noticed that my application starts and consumes several times more memory than equivalent native applications. The problem is that whenever I open/close windows in my application, the memory that it occupies grows more. I wait and nothing happens. Shouldn't GC release the memory as long as an object is not referenced any more? Thank you, -- Petros
Show quote
"Petros Amiridis" <pet***@nowhere.net> wrote in message I think to some degree it's a waste of time trying to help GC do its job news:OyV$mvOlGHA.1204@TK2MSFTNGP02.phx.gbl... > Phil Wilson wrote: > >> You example doesn't help because there's nothing in Foo that needs >> disposing, and Dispose isn't related to GC as you seem to be assuming. > > What if it does have something that needs disposing? An if Dispose > doesn't have anything to do with GC, could tell me briefly what are > good practices that can make your application consume less memory? > > I've noticed that my application starts and consumes several times more > memory than equivalent native applications. The problem is that > whenever I open/close windows in my application, the memory that it > occupies grows more. I wait and nothing happens. Shouldn't GC release > the memory as long as an object is not referenced any more? > better in the way it seems you're thinking, as it is a fairly indeterminate mechanism in the first place. It is somewhat important in some cases to help GC have less to do though, because it can become a performance issue. For example, using lots of stringbuilders for what are really just simple concatenations. But that really manifests itself as a performance issue more than a memory one in my testing. As somebody else said, the Dispose pattern is for making sure UNMANAGED resources inside your classes get cleaned up. That is, making sure there are no memory leaks in things that GC doesn't try to deal with. That's why the statement "Dispose doesn't have anything to do with GC". I have no idea what "several times more memory than equivalent native applications" means. Equivalent how -Functionality? Code? That's such a nebulous comparison I don't think I'd spend much time worrying about that either. Is there a specific problem you're having or specific reason you think you may have a memory leak in the application? Daniel Billingsley wrote:
> As somebody else said, the Dispose pattern is for making sure This more clear to me now. I really thought Dispose would help GC.> UNMANAGED resources inside your classes get cleaned up. Thank you and the rest for the clarification. > I have no idea what "several times more memory than equivalent native I admit that is based entirely on my experience and not in crystal> applications" means. Equivalent how -Functionality? Code? That's > such a nebulous comparison I don't think I'd spend much time worrying > about that either. clear measurements. My heuristics mechanism takes under consideration all the factors: Functionality, Number of Forms etc. Sure, I might be inaccurate in my comparison, but the numbers are very different between native and managed applications. My native applications take memory and give it back as soon as I don't need the resources I've used. In managed applications, the memory keeps being eaten until the GC decides it is time to collect. The problem with this is that my customer does run more applications than one. The customer also uses his computer for other puproses, so she runs third party applications too. So to conclude, I don't have a specific problem, other than the need to tell my customers to add some more memory to their machines. Maybe it is not a leak, it is just taking the GC a long time to collect back the memory. -- Petros
Show quote
"Petros Amiridis" <pet***@nowhere.net> wrote in message The GC will kick in when required - for example memory is low, but it will news:ewLX8WTlGHA.3396@TK2MSFTNGP05.phx.gbl... > Daniel Billingsley wrote: > >> As somebody else said, the Dispose pattern is for making sure >> UNMANAGED resources inside your classes get cleaned up. > > This more clear to me now. I really thought Dispose would help GC. > Thank you and the rest for the clarification. > >> I have no idea what "several times more memory than equivalent native >> applications" means. Equivalent how -Functionality? Code? That's >> such a nebulous comparison I don't think I'd spend much time worrying >> about that either. > > I admit that is based entirely on my experience and not in crystal > clear measurements. My heuristics mechanism takes under consideration > all the factors: Functionality, Number of Forms etc. Sure, I might be > inaccurate in my comparison, but the numbers are very different between > native and managed applications. My native applications take memory and > give it back as soon as I don't need the resources I've used. In > managed applications, the memory keeps being eaten until the GC decides > it is time to collect. The problem with this is that my customer does > run more applications than one. The customer also uses his computer for > other puproses, so she runs third party applications too. So to > conclude, I don't have a specific problem, other than the need to tell > my customers to add some more memory to their machines. Maybe it is not > a leak, it is just taking the GC a long time to collect back the memory. only release managed objects if: A. They have been marked to be Diposed or B. They are unreachable on the heap. Regards Simon. Simon Hart wrote:
Show quote > "Petros Amiridis" <pet***@nowhere.net> wrote in message Actually only condition B is relevant.> news:ewLX8WTlGHA.3396@TK2MSFTNGP05.phx.gbl... >> Daniel Billingsley wrote: >> >>> As somebody else said, the Dispose pattern is for making sure >>> UNMANAGED resources inside your classes get cleaned up. >> This more clear to me now. I really thought Dispose would help GC. >> Thank you and the rest for the clarification. >> >>> I have no idea what "several times more memory than equivalent native >>> applications" means. Equivalent how -Functionality? Code? That's >>> such a nebulous comparison I don't think I'd spend much time worrying >>> about that either. >> I admit that is based entirely on my experience and not in crystal >> clear measurements. My heuristics mechanism takes under consideration >> all the factors: Functionality, Number of Forms etc. Sure, I might be >> inaccurate in my comparison, but the numbers are very different between >> native and managed applications. My native applications take memory and >> give it back as soon as I don't need the resources I've used. In >> managed applications, the memory keeps being eaten until the GC decides >> it is time to collect. The problem with this is that my customer does >> run more applications than one. The customer also uses his computer for >> other puproses, so she runs third party applications too. So to >> conclude, I don't have a specific problem, other than the need to tell >> my customers to add some more memory to their machines. Maybe it is not >> a leak, it is just taking the GC a long time to collect back the memory. > > The GC will kick in when required - for example memory is low, but it will > only release managed > objects if: A. They have been marked to be Diposed or B. They are > unreachable on the heap. > > Regards > Simon. You can't mark objects to be collected, the only way to make them collectable is to make them unreachable. Daniel Billingsley wrote:
> As somebody else said, the Dispose pattern is for making sure I would take exception with that statement. Dispose is for making sure > UNMANAGED resources inside your classes get cleaned up. resources that are not simply managed heap allocations get cleaned up. Unmanaged resources such as handles or Win32 memory allocations are fine examples of such, but there are certainly managed examples as well. A common example of a managed resource that needs to be explicitly cleaned up is a callback (delegate) which can keep an object alive long after you're done with it, consuming both memory and CPU resources making callbacks to an object that no one cares about anymore. -cd Agree. We often use the Dispose (IDisposable) for cleaning managed resources
as well as unmanaged. We tend to use the Finalizer (Destructor) for unmanaged deallocation. Regards Simon. Show quote "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> wrote in message news:uuTrPmTlGHA.4536@TK2MSFTNGP04.phx.gbl... > Daniel Billingsley wrote: >> As somebody else said, the Dispose pattern is for making sure >> UNMANAGED resources inside your classes get cleaned up. > > I would take exception with that statement. Dispose is for making sure > resources that are not simply managed heap allocations get cleaned up. > Unmanaged resources such as handles or Win32 memory allocations are fine > examples of such, but there are certainly managed examples as well. A > common example of a managed resource that needs to be explicitly cleaned > up is a callback (delegate) which can keep an object alive long after > you're done with it, consuming both memory and CPU resources making > callbacks to an object that no one cares about anymore. > > -cd > > Simon Hart wrote:
> Agree. We often use the Dispose (IDisposable) for cleaning managed resources Could you explain why you prefer the finalizer instead of a manual call > as well as unmanaged. We tend to use the Finalizer (Destructor) for > unmanaged deallocation. to Dispose for freeing unmanaged resources? As far as I know you can never tell when the GC will finalize an object. So it might keep floating around forever as well. Which means that you could run out of handles for example. Maybe I've misunderstood something behind GC and the finalizer?. Max Markus Stoeger wrote:
Show quote > Simon Hart wrote: No, that is correct.>> Agree. We often use the Dispose (IDisposable) for cleaning managed >> resources as well as unmanaged. We tend to use the Finalizer >> (Destructor) for unmanaged deallocation. > > Could you explain why you prefer the finalizer instead of a manual call > to Dispose for freeing unmanaged resources? > > As far as I know you can never tell when the GC will finalize an object. > So it might keep floating around forever as well. Which means that you > could run out of handles for example. > > Maybe I've misunderstood something behind GC and the finalizer?. > > Max The Dispose method should be used to free resources. The finalizer should call Dispose as a backup if the program failed to call it.
Show quote
"Göran Andersson" <gu***@guffa.com> wrote in message More specifically, the recommended structure for Finalize and Dispose is:news:evglUFYlGHA.2128@TK2MSFTNGP04.phx.gbl... > Markus Stoeger wrote: >> Simon Hart wrote: >>> Agree. We often use the Dispose (IDisposable) for cleaning managed >>> resources as well as unmanaged. We tend to use the Finalizer >>> (Destructor) for unmanaged deallocation. >> >> Could you explain why you prefer the finalizer instead of a manual call >> to Dispose for freeing unmanaged resources? >> >> As far as I know you can never tell when the GC will finalize an object. >> So it might keep floating around forever as well. Which means that you >> could run out of handles for example. >> >> Maybe I've misunderstood something behind GC and the finalizer?. >> >> Max > > No, that is correct. > > The Dispose method should be used to free resources. The finalizer should > call Dispose as a backup if the program failed to call it. class C : IDisposable { void IDisposable.Dispose() { Dispose(true); } ~C() { Dispose(false) } protected virtual void Dispose(bool disposing) { if (disposing) { // free managed resources here GC.SuppressFinalize(this); } // free unmanaged resources here } } The C++/CLI compiler automatically implements this structure, while in C#/VB you have to do it yourself. Current versions of FxCop will raise warnings if your class implements IDisposable but doesn't do it this way. Of course, if your class cannot be derived from, then there's no need for Dispose(bool) to be virtual. -cd -cd I don't know about the C# environment, but VB 2005 can be configured to
insert the dispose pattern, as well as other implementation patterns, when you add the Implements clause to the class definition and press return. Mike Ober. Show quote "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> wrote in message news:%23V$RCfYlGHA.1240@TK2MSFTNGP05.phx.gbl... > "Göran Andersson" <gu***@guffa.com> wrote in message > news:evglUFYlGHA.2128@TK2MSFTNGP04.phx.gbl... > > Markus Stoeger wrote: > >> Simon Hart wrote: > >>> Agree. We often use the Dispose (IDisposable) for cleaning managed > >>> resources as well as unmanaged. We tend to use the Finalizer > >>> (Destructor) for unmanaged deallocation. > >> > >> Could you explain why you prefer the finalizer instead of a manual call > >> to Dispose for freeing unmanaged resources? > >> > >> As far as I know you can never tell when the GC will finalize an object. > >> So it might keep floating around forever as well. Which means that you > >> could run out of handles for example. > >> > >> Maybe I've misunderstood something behind GC and the finalizer?. > >> > >> Max > > > > No, that is correct. > > > > The Dispose method should be used to free resources. The finalizer should > > call Dispose as a backup if the program failed to call it. > > More specifically, the recommended structure for Finalize and Dispose is: > > class C : IDisposable > { > void IDisposable.Dispose() > { > Dispose(true); > } > > ~C() > { > Dispose(false) > } > > protected virtual void Dispose(bool disposing) > { > if (disposing) > { > // free managed resources here > > GC.SuppressFinalize(this); > } > > // free unmanaged resources here > } > } > > The C++/CLI compiler automatically implements this structure, while in C#/VB > you have to do it yourself. Current versions of FxCop will raise warnings > if your class implements IDisposable but doesn't do it this way. > > Of course, if your class cannot be derived from, then there's no need for > Dispose(bool) to be virtual. > > -cd > > -cd > > Let's talk. :)
This would apply to simple events then, since they are really just fancy delegates. I've never heard of anybody talk of implementing Dispose in a class just because it raises events. Should we? Let's lay some groundwork. The problem with keeping an object "alive" is because something references it, not the other way around. Let's imagine an ObjectB that has a reference to ObjectA because ObjectA was previously hooked to an event in ObjectB (creating a delegate reference as you describe). Now ObjectB goes out of scope. It obviously isn't "making callbacks" any more, so there's no reason for it to have Dispose() for that reason. The problem with keeping ObjectA "alive" consuming memory is only temporary until GC does its thing with ObjectB. That's the whole point of GC. But, for you GC gurus - isn't GC smart enough to know that the only reference to ObjectA is from a "dead" ObjectB and therefore consider ObjectA itself eligible for collection? Show quote "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> wrote in message news:uuTrPmTlGHA.4536@TK2MSFTNGP04.phx.gbl... > Daniel Billingsley wrote: >> As somebody else said, the Dispose pattern is for making sure >> UNMANAGED resources inside your classes get cleaned up. > > I would take exception with that statement. Dispose is for making sure > resources that are not simply managed heap allocations get cleaned up. > Unmanaged resources such as handles or Win32 memory allocations are fine > examples of such, but there are certainly managed examples as well. A > common example of a managed resource that needs to be explicitly cleaned > up is a callback (delegate) which can keep an object alive long after > you're done with it, consuming both memory and CPU resources making > callbacks to an object that no one cares about anymore. > > -cd > >
Show quote
"Daniel Billingsley" <DanielBillingsley@newsgroup.nospam> wrote in message Yes it is. I have explicitely tested this scenerio.news:eJvcc9elGHA.4100@TK2MSFTNGP05.phx.gbl... > Let's talk. :) > > This would apply to simple events then, since they are really just fancy > delegates. I've never heard of anybody talk of implementing Dispose in a > class just because it raises events. Should we? > > Let's lay some groundwork. The problem with keeping an object "alive" is > because something references it, not the other way around. Let's imagine an > ObjectB that has a reference to ObjectA because ObjectA was previously > hooked to an event in ObjectB (creating a delegate reference as you > describe). > > Now ObjectB goes out of scope. It obviously isn't "making callbacks" any > more, so there's no reason for it to have Dispose() for that reason. The > problem with keeping ObjectA "alive" consuming memory is only temporary > until GC does its thing with ObjectB. That's the whole point of GC. > > But, for you GC gurus - isn't GC smart enough to know that the only > reference to ObjectA is from a "dead" ObjectB and therefore consider ObjectA > itself eligible for collection? Mike. Show quote > > "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> > wrote in message news:uuTrPmTlGHA.4536@TK2MSFTNGP04.phx.gbl... > > Daniel Billingsley wrote: > >> As somebody else said, the Dispose pattern is for making sure > >> UNMANAGED resources inside your classes get cleaned up. > > > > I would take exception with that statement. Dispose is for making sure > > resources that are not simply managed heap allocations get cleaned up. > > Unmanaged resources such as handles or Win32 memory allocations are fine > > examples of such, but there are certainly managed examples as well. A > > common example of a managed resource that needs to be explicitly cleaned > > up is a callback (delegate) which can keep an object alive long after > > you're done with it, consuming both memory and CPU resources making > > callbacks to an object that no one cares about anymore. > > > > -cd > > > > > > Yes, it is.
When the GC does it's thing, it starts out by considering all objects as collectable, then looks for references to find out which objects are not collectable. As it doesn't look in collectable objects for references, it still sees that unreachable objects are collectable although they reference each other. "Every object charged with being collectable will be presumed guilty until proved reachable." ;) Daniel Billingsley wrote: Show quote > Let's talk. :) > > This would apply to simple events then, since they are really just fancy > delegates. I've never heard of anybody talk of implementing Dispose in a > class just because it raises events. Should we? > > Let's lay some groundwork. The problem with keeping an object "alive" is > because something references it, not the other way around. Let's imagine an > ObjectB that has a reference to ObjectA because ObjectA was previously > hooked to an event in ObjectB (creating a delegate reference as you > describe). > > Now ObjectB goes out of scope. It obviously isn't "making callbacks" any > more, so there's no reason for it to have Dispose() for that reason. The > problem with keeping ObjectA "alive" consuming memory is only temporary > until GC does its thing with ObjectB. That's the whole point of GC. > > But, for you GC gurus - isn't GC smart enough to know that the only > reference to ObjectA is from a "dead" ObjectB and therefore consider ObjectA > itself eligible for collection? > > "Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> > wrote in message news:uuTrPmTlGHA.4536@TK2MSFTNGP04.phx.gbl... >> Daniel Billingsley wrote: >>> As somebody else said, the Dispose pattern is for making sure >>> UNMANAGED resources inside your classes get cleaned up. >> I would take exception with that statement. Dispose is for making sure >> resources that are not simply managed heap allocations get cleaned up. >> Unmanaged resources such as handles or Win32 memory allocations are fine >> examples of such, but there are certainly managed examples as well. A >> common example of a managed resource that needs to be explicitly cleaned >> up is a callback (delegate) which can keep an object alive long after >> you're done with it, consuming both memory and CPU resources making >> callbacks to an object that no one cares about anymore. >> >> -cd >> Petros Amiridis wrote:
> Hi, Sure. If an object is IDisposable, you have to call Dispose on it sooner > > When I create an instance of one of my classes inside a method, does it > make a difference if I call its Dispose method? or later (not necessarly in the same method). If you don't, you might create a resource leak which will make your program randomly throw OutOfMemoryExceptions at your users. Calling Dispose has no effect on when the memory of your managed objects will get freed by the GC though. hth, Max |
|||||||||||||||||||||||