12

If I have a console application with code like:

using (DisposableObject object = new DisposableObject())
{
   if (a condition)
     Environment.Exit(0);

   // Do Stuff
}

Will my object be properly disposed? Or does the thread die before the object is cleaned up?

RJ Cuthbertson
  • 1,458
  • 1
  • 20
  • 36
  • Note that if you're shutting down the application, even if the object is not Disposed, you won't actually leak memory (as the process protected memory space is completely freed once the process terminates.) Other things could go wrong if Disposal has more persistent side effects (like committing to a database or something that lives beyond the process scope.) – Dan Bryant Oct 31 '12 at 19:15
  • 1
    @DanBryant an unreleased resource won't leak *managed* memory. If the unmangaged resource is unmanaged memory (possibly due to interop with an unmanged language) then you could have unreleased memory. – Servy Oct 31 '12 at 19:16
  • I'm actually using it on a `SqlConnection`, but that `using` block is nested within two others (SharePoint objects). I just wanted to be sure the `Dispose()` methods would be called as not disposing of the SP objects generates errors in the logs. – RJ Cuthbertson Oct 31 '12 at 19:18
  • hmm... maybe it's time to rethink the `Environment.Exit()` approach to doing things? – code4life Oct 31 '12 at 19:35
  • I can always throw an exception. – RJ Cuthbertson Oct 31 '12 at 19:37

2 Answers2

11

Your application will terminate and all managed memory will be released at that point.

The generated finally block will not execute, so any Dispose methods will not be called, so any non-managed resources may very well not be released.

See Don't Blindly Count on a Finalizer.

3dGrabber
  • 4,710
  • 1
  • 34
  • 42
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Would the `// Do Stuff` code be executed? What does `Environment.Exit(0);` do exactly? – Olivier Jacot-Descombes Oct 31 '12 at 19:14
  • `// Do Stuff` won't be executed. `Environment.Exit(0)` kills the thread and returns 0 from main. – RJ Cuthbertson Oct 31 '12 at 19:15
  • @OlivierJacot-Descombes - `// Do Stuff` will not execute. The call simply terminates the process (returning an error code - the passed in `int`). – Oded Oct 31 '12 at 19:15
  • The finally block will not execute, the Exit() statement terminates the thread. Try it. Didn't vote on this one btw. – Hans Passant Oct 31 '12 at 19:23
  • @HansPassant - Thanks for correcting me. Answer updated to reflect actual behaviour. – Oded Oct 31 '12 at 19:29
  • 1
    @rj - You are worried about memory leaks. That doesn't make much sense in general, a terminated process doesn't leak memory. Nor does IDisposable have anything to do with memory. The only thing you could worry about is the very small corner case where the class has a finalizer and it does something different when the finalizer cleans up instead of Dispose(). Don't write finalizers. – Hans Passant Oct 31 '12 at 19:30
  • @HansPassant, I'll update my post. I'm not actually concerned about a memory leak. I'm concerned about generation of an error in a log. – RJ Cuthbertson Oct 31 '12 at 19:31
  • @rjcup3 - As soon as `Environment.Exit` is called, that's it. You can't write to a log at that time, but if you have an open handle to the file, it will very will remain open and you can't open/write to that file anymore. – Oded Oct 31 '12 at 19:33
  • 1
    I'm not writing to the log. They're SharePoint objects. If you don't dispose, SharePoint will take care of that for you, but generates an error in the log that says you didn't dispose properly. I'm testing now (trying to force this behavior). – RJ Cuthbertson Oct 31 '12 at 19:36
  • I want to write and flush log when console is closing. I still can not understand how to do it. – Denis535 Apr 21 '19 at 23:10
1

Resources that the operating system knows about will generally be cleaned up when an application exits. Resources that the operating system does not know about will generally not be cleaned up.

For example, some programs which uses a database and need to implement a locking paradigm which is different from anything the database server supports directly may use one or more "LockedResources" tables to keep track of what resources should be locked. Code which needs to acquire a resource will lock the "LockedResources" table, update it to show what resources need to be locked, and then release it; that operation on the "LockedResource" table will generally be quite quick (so the "LockedResource" table will locked only briefly), even if the application needs to hold the real resource for a long time. If, however, the application does an Environment.Exit while the "LockedResources" table says it owns a resource, the operating system will have no clue how to update the "LockedResources" table to cancel such ownership.

In general, things like database applications should be designed to be robust even if a client application unexpectedly dies. For example, there could be a table of active clients, with each active client holding a lock on a record which identifies itself. If a client that wants to use a resource notices that "LockedResources" table has it checked out to some other client, the former client could check to ensure that the latter client's entry in the "active clients" table is still locked. If not, it could figure that the client in question has died and take appropriate action (recognizing that the client that died might have left its resource in a bad state). On the other hand, the fact that database should be designed to be robust if clients die unexpectedly doesn't mean they always are. Resource abandonment is not a good thing, even if it is usually survivable.

supercat
  • 77,689
  • 9
  • 166
  • 211