In my Windows Form application when I close a form (which is derived from a base form), its FormClosing and FormClosed Events fire but destructor never fires off. It still keeps the memory occupied.
Any ideas on how to destroy the form completely when it is closed?
If it's not destroyed that means the Garbage Collector doesn't think it should be destroyed.
This basically means that you're either:
Holding a reference to the object somewhere
Have the object listening to an event (That's also a kind of reference to the object)
The garbage collector won't free the Form until there are no references to it.
If you have important resources you want to dispose of, make it IDisposable, and use the Dispose method.
Destructors (or more correctly, finalizers - there are no destructors in .NET) are not guaranteed to be executed in .NET - objects may be cleaned up at the whim of the runtime or even never. You cannot rely on your finalizer method ever being called.
If you need to do something when your form is closed, handle the Closed event.
If you need to release an unmanaged resource (e.g. close an open file), add this logic to the Dispose() method.
If you are worried about memory use, do not worry about memory use. The runtime manages memory automatically based on its own logic.
Reference: Garbage Collection (MSDN)
Related
Let's say there are two apartment-threaded COM objects, located in different apartments. Or maybe they're in different processes altogether. If one object calls a method on another, which in turn calls a method back on the first object, how does COM prevent the whole thing from deadlocking?
What you describe is called reentrancy.
The truth is that COM doesn’t do anything explicit to prevent reentrancy issues. It’s up to the implementer of each object to take precautions where needed, as applicable.
Funny enough, reentrancy in COM is far less common in real life than you would think. Object graphs in COM tend to be mostly trees, which do not exhibit reentrancy. When you have cycles it’s almost always because of objects exposing event-type functionality of some sort, typically Connection Points.
Event callbacks are very limited in scope and they trigger under the explicit control of each object’s code, so the programmer is able to easily time them so they occur at safe places (for example at/near the end of a method’s body after all the real work is done). This prevents serious reentrancy issues from developing.
But nothing stops you from coding something dangerous. For example, if an object triggers an event while its internal object state is inconsistent, all bets are off.
You mention deadlocks. Deadlocks require a locking mechanism of some sort (for example a Critical Section) and should be extremely rare to impossible in COM apartments for the reasons listed above. Any object that triggers an event while holding a lock is asking for serious trouble, and a deadlock is not the biggest of its worries: by virtue of being an STA object the reentrant call will run on the same thread, and it will be able to acquire the locks again and proceed right through, which means it’s very likely that the object will corrupt its internal state, cause a crash, or worse. Note that locks in an STA thread only make sense if the resources controlled by the lock are accessible to threads outside the object’s STA.
And finally, nothing in COM stops you from causing an infinite recursion loop and subsequent stack overflow either. For example, take two COM objects Obj1 and Obj2, with Obj2 implementing an event. We can have Obj1 call a pObj2->SomeMethod(…) which causes Obj2 to fire the event; then have obj1 listen (“sink”) to that event, and have that event handler call SomeMethod() again.
UPDATE:
Profound thanks to Remy Lebeau for pointing to in his comment something I had forgotten to discuss, via a link to CodeGuru article Understanding COM Apartments, Part I. And in the process I also learned something new myself I should have known about.
There is one aspect of reentrancy and locking to consider and that is what happens during inter-apartment calls (either STA<->STA, STA<->MTA, or even STA<->OutofProc). During an inter-apartment call the STA (caller's) thread needs to stall and wait for an answer to the call request; the response cannot (by definition) execute on the same thread. But it can't just fully block (e.g. WaitForSingleObject) waiting for the response because the thread needs to be able to respond and process not only potential callbacks to the original object, but also to callbacks to any other object inside of the same apartment. If it were to fully block, the COM infrastructure itself would be introducing the potential for a deadlock and you wouldn't even need a dependency cycle between objects. So the COM marshalling infrastructure uses a more complex form of Wait that can unblock for a few other situations (Hans Passat points to CoWaitForMultipleHandles which looks right to me but I don't know the infrastructure to that level). If an applicable callback occurs, the marshalling infrastructure will unblock and allow that call to enter the apartment and proceed.
This is a form of locking induced by the COM infrastructure itself, rather than one coded explicitly as part of the object's implementation, which is why I hadn't thought of bringing it up. So COM does in fact "do something to prevent deadlocks", but to prevent deadlock potentials induced by its own infrastructure.
The part that I hadn't consciously realized was that this mechanism is very selective. It only lets through COM calls that form part of the same causality chain, that is, a callback, a direct consequence of the call that the thread was waiting on. Other COM calls into the apartment have to queue up and wait for that call chain to conclude, and for the STA thread to return to the thread's message loop.1
1 It makes complete sense that it needs to be that way, but I don't think I ever realized it.
In my application I'm creating some JS objects, and also on C++ side some objects for running some handling.
I would like to delete C++ objects when they are not needed anymore: the corresponding JS object is Garbage Collected.
I'm trying to find that in Cobalt source code/documentation but I cannot find that. I do see ScriptValue::Reference but this seems to be the opposite:
Prevent a JS object from being garbage collected by declaring a relation between a JS value and C++ object.
Could someone give some hints how this can be achieved? (getting some callback called in C++ when an object is garbage collected).
Any C++ class exposed to JavaScript must inherit (directly or indirectly) script::Wrappable which has a virtual destructor. This destructor will be called when a corresponding JavaScript object is destroyed, either as a result of garbage collection or JS VM teardown.
Usual caveats apply: GC order and timing are non-deterministic. If you need to free critical resources as soon as possible, expose explicit cleanup methods to JavaScript.
See cobalt::dom::Node::~Node() for example of a cleanup performed upon destruction.
Here's my situation:
I have .NET wrapper-objects in a C++/CLI layer that hold pointers to unmanaged C++ objects. I've implemented the finalizer so that it deletes the unmanaged memory pointed to by the wrapper-object on garbage-collection and sets the pointer to null.
Here's the problem:
I'm watching the finalizer for the .NET wrapper-object and it gets called twice and tries to delete the same memory twice, indicating that I have somehow created 2 .NET wrapper objects that go out-of-scope, and are garbage collected while I'm still expecting the wrapper object to be in scope (these wrapper objects are getting passed to a VB.NET application).
Here's my question:
Is there anyway for me to check the handle value so that I can confirm where the wrapper objects are getting created (copied or whatever)? Currently I'm looking at the handle values (EG - 0x0014fe80), but I see 3 different values for when the object is created, added to a collection, and deleted. So I'm not sure if the GC is just moving stuff around and this is the same object, or if I'm actually seeing 3 different objects that reference the same unmanaged memory. I would like to resolve the duplicate object copies if possible, but I understand that I will probably want to implement some sort of smart pointer so that this doesn't happen.
Thanks,
Ian
Take a look at this question
Here is an implementation of a scoped_ptr that is noncopyable and has an auto-release mechanism for unmanaged objects, by #Ben Voigt
Yeah, I ended up modifying an auto_ptr class to be a shared pointer to ensure that the unmanaged memory is only deleted once through the smart pointer finalizer. I'm assuming I did something similar to all the other implementations; I created a static dictionary in the auto_ptr template class, using the native pointer value as the key, that is checked every time the finalizer is called to update the count of each item, or delete the memory.
I have a form with the following fields:
List<String^> ^images;
PictureBox ^box;.
List<PictureBox^> ^boxes;
String ^path;
(as well as some ints).
I allocate the memory for each of these with gcnew, but when I close the form, the memory is not freed. I thought they would be garbage collected; why are they not?
I also noticed an autogenerated components variable of type Container ^ that's deleted in the destructor. What's up with that?
EDIT: Whoops, forgot one rather important thing: In the main form from which I call the above forms, I have a List of these forms (to communicate with them). How should I remove the form from the list once it's closed?
Garbage collection is indeterminate; you can't predict when it will run. All that's guaranteed is that it will run "when it needs to"; if you absolutely need to control when it happens, then you can call:
GC.Collect();
and
GC.WaitForPendingFinalizers();
When I've registered an object foo to receive KVO notifications from another object bar (using addObserver:...), if I then deallocate foo do I need to send a removeObserver:forKeyPath: message to bar in -dealloc?
You need to use -removeObserver:forKeyPath: to remove the observer before -[NSObject dealloc] runs, so yes, doing it in the -dealloc method of your class would work.
Better than that though would be to have a deterministic point where whatever owns the object that's doing the observing could tell it it's done and will (eventually) be deallocated. That way, you can stop observing immediately when the thing doing the observing is no longer needed, regardless of when it's actually deallocated.
This is important to keep in mind because the lifetime of objects in Cocoa isn't as deterministic as some people seem to think it is. The various Mac OS X frameworks themselves will send your objects -retain and -autorelease, extending their lifetime beyond what you might otherwise think it would be.
Furthermore, when you make the transition to Objective-C garbage collection, you'll find that -finalize will run at very different times — and in very different contexts — than -dealloc did. For one thing, finalization takes place on a different thread, so you really can't safely send -removeObserver:forKeyPath: to another object in a -finalize method.
Stick to memory (and other scarce resource) management in -dealloc and -finalize, and use a separate -invalidate method to have an owner tell an object you're done with it at a deterministic point; do things like removing KVO observations there. The intent of your code will be clearer and you will have fewer subtle bugs to take care of.
A bit of extra info that I've gained by painful experience: although NSNotificationCenter uses zeroing weak references when running under garbage collection, KVO does not. Thus, you can get away with not removing an NSNotificationCenter observer when using GC (when using retain/release, you still need to remove your observer), but you must still remove your KVO observers, as Chris describes.
Definitely agree with Chris on the "Stick to memory (and other scarce resource) management in -dealloc and -finalize..." comment. A lot of times I'll see people try to invalidate NSTimer objects in their dealloc functions. The problem is, NSTimer retains it's targets. So, if the target of that NSTimer is self, dealloc will never get called resulting in some potentially nasty memory leaks.
Invalidate in -invalidate and do other memory cleanup in your dealloc and finalize.