[.net] The joy of garbage collection

This topic is 4614 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

OK, I'm new to C#, but I have just hit a rather annoying problem. I have a logManager class, which basically is a HashMap with a few helper functions to create, open and close logs. The hashmap contains instances of a Log class which, quite obviously, represent individual logs. I'd like LogManager to close all the logs it contains during it's destruction, but it seems that some (all ?) the logs are destroyed BEFORE the manager, even tough the manager maintains reference to them. Sure I could call logManager.closeAll() manually before program termination since the destructors quite obviously throw exceptions, but that feels quite hackish. Anyone got any clues ?

Share on other sites
You mean your manager contains the log files? if thats the case, shouldn't the log files be destroyed before the manager because of their scope

Share on other sites
Show us some code. Your explanation is not very clear...

Destruction (Finalization)in C# is NOT determenistic (is that the right word?). That is why they invented Dispose...

Check this out.

Cheers

Share on other sites
Use the disposing pattern.

public class Blah : IDisposable {  void IDisposable.Dispose() {    Dispose(true);    GC.SuppressFinalize(this);  }  protected void Dispose(bool disposing) {    if(!disposed) {      if(disposing) {        //release your managed resources here      }      //release unmanaged resources here    }  }  ~Blah() {    Dispose(false);  }  private bool disposed = false;}

Then you can just call the Dispose method and it will (assuming you code it right) release the resources.

Share on other sites
The specifications allow you to do very little in a Finalizer. Notably, the order in which Finalizers are called is not guaranteed, and so, in general, you cannot call methods of member's instance. Obviously, that's what happens here: the GC has finalized your logs before the LogManager, even if the LogManager holds a reference to them. And the .NET specs say it's allowed (which makes sense: in which order will you finalize a graph with circular references ?).

IMO, Finalizers have only 1 usage: release unmanaged resources, if they haven't been released by the IDisposable pattern before. (Don't forget to remove the finalizer if you don't need it, because finalization has a big impact on performances).

Quote:
 Sure I could call logManager.closeAll() manually before program termination since the destructors quite obviously throw exceptions, but that feels quite hackish.

I don't see it hackish. Calling CloseAll() before the program exits looks normal and expected to me. Remember that .NET Finalizers are very different from C++ destructors, and that you should not use them in the same way! Otherwise, you might get into trouble - which you obviously did ;-)

You may find the following reads interesting:
A discussion precisely on this problem, on the dotnet.languages.csharp newsgroup. Look for the thread "Destructors are useless?".
A small article about it (the newsgroup is a lot more interesting): http://www.developer.com/net/csharp/article.php/2233111

Best,
jods