I am trying to figure out how to properly clean up after my objects in C++/CLI.
I have read or skimmed these two articles (one, two) and looked at the standard and looked at some other questions notably this one.
I have various pieces of information:
- The finalizer should clean up unmanaged resources (so everything gets cleaned up when the object is garbage-collected.
- The destructor should clean up managed resources (delete Foo or Foo.Dispose()?) and call the finalizer (according to 1)
- Both the destructor and the finalizer can be called multiple times (see 3 p. 26 end of 8.8.8)
- If the destructor is called the finalizer won't be called anymore (according to 1) (not by the CLR, that is, you can still call it yourself)
- The destructor will call base class destructors (see 3 p. 25)
- A class that has a finalizer should always have a destructor (presumably to deterministically clean up the unmanaged resources)
- A call to a finalizer will not call the base class finalizer (3 19.13.2 p. 131)
But there is also much confusion caused in part by the fact that
- finalizers are called destructors in C#
- the destructor internally generates Dispose and Finalize methods (not sure about Finalize) but the Finalize method is NOT the finalizer
- the semantics of destructors are different in C++ and the complexity of having both deterministic clean-up und garbage collection in general
What I would like as an answer is an example of a class with all the different kinds of data that it might contain (managed, unmanaged, managed but disposable, whatever else you can think of) and properly written destructor and finalizer.
I have two more specific question:
- Would it be acceptable to deal with the possibility of being called multiple times by just having a
bool hasBeenCleanedUp
member and making the entire code in the destructor/finalizer conditional on that? - What kind of data can only be cleaned up by the destructor but must not be cleaned up in the finalizer because it may have been cleaned up by the gc?