Is there a time to ignore IDisposable.Dispose?

Of course, we must call Dispose () on IDisposable objects as soon as we don't need them (which is often just a “using” statement). If we do not take this precaution, then bad things can happen, from thin to stopping the show.

But what about the “last moment” before the process is completed? If your IDisposables have not been explicitly deleted at this point in time, is it true that it no longer matters? I ask because the unmanaged resources under the CLR are represented by kernel objects - and terminating the win32 process in any case will release all unmanaged resources / kernel objects. In other words, not a single resource will “leak” after the process is complete (regardless of whether Dispose () was called for IDisposables that delay).

Can anyone think of a case where terminating the process will still leave a missed resource, simply because Dispose () did not explicitly call one or more IDisposables?

Please do not misunderstand this question: I am not trying to justify ignoring IDisposables. The question is only technical and theoretical.

EDIT: What about mono on Linux? Is the process terminated there as “reliable” when cleaning unmanaged “leaks”?

LAST EDIT. Although there may be a “different use” for IDisposables, the focus is on resource leaks. I heard two answers: (1) if your process refuses to stop working, you will have a leak, and (2) yes, the resources may leak even if the process ends. Of course, I agree with paragraph (1), although it goes beyond what I need. Otherwise, paragraph (2) is exactly what I am looking for, but I cannot shake the feeling, it is just an assumption. Jeffrey Richter ("Windows through C / C ++") explains that a (gracefully) terminated Win32 process will not leave any missed or lost resources. Why will the process containing the CLR change? Where is the documentation, a specific example, or a theoretical scenario that gives an idea that the ability to clean up a Win32 process is compromised when using the CLR?

+6
c # memory-leaks process idisposable dispose
source share
5 answers

From a technical point of view, it all depends on what IDisposable does. It has been used for many things, not just unmanaged resources.

For example, when working on an Outlook application, I created a small abstraction of the Outlook API. Attachments were especially annoying for working with streams, because you had to save them in a temporary file, work with it, and then clean it.

So my abstraction looked something like this:

OutlookMailItem mailItem = blah; using (Stream attachmentStream = mailItem.OpenAttachment("something.txt")) { // work with stream } 

When Dispose is called in an AttachmentStream, the temporary file on which it was based was deleted. In this case, if Dispose was not called, the temp file will never be cleared. I had a startup process to look for these lost files, but I decided to introduce this as an example.

In fact, almost all IDisposable implementations that wrap a socket, descriptor, or transaction will simply be cleared by the operating system after the process is complete. But it is obvious that, as well-being. Avoid it if you can.

+2
source share

During the completion of collaboration, AppDomain is unloaded, which leads to the execution of all finalizers:

From the Object.Finalize documentation:

During a domain shutdown, Finalize is automatically called for objects that are not exempted from completion, even those that are still available.

So, you are safe at shutdown if two criteria are satisfied:

  • Each IDisposable object that is still alive has a correctly implemented finalizer (true for Framework classes may not apply to less trustworthy libraries); and

  • This is actually a joint shutdown, not an abnormal shutdown, such as terminating a hard process, Ctrl-C in a console application, or Environment.FailFast .

If either of these two criteria is not met, it is possible that your application is holding global unmanaged resources (such as mutexes) that will actually leak. Therefore, it is always best to call Dispose earlier if you can. In most cases, you can rely on the CLR and object finalizers to do the job for you, but it's better to be safe than sorry.

+2
source share

One thing that I often find available is serial ports — now that the serial port needs to be freed up when the program starts, other programs cannot access the serial port while it is being held by another process. So, if your process refuses to die, then you bind the serial port. This can be very bad if the user tries to restart your program, but the zombie version of the previous process still clings to the serial port.

And yes, I used to have my program in a zombie state, and then the client complained that the program no longer works, because the program can not connect to the serial port when it restarts. The result is either a walk of the user, or the destruction of the process in the task manager, or reboot, none of which is a particularly convenient task for the user.

+1
source share

You write your own code for free objects in your one-time class. It is for you to write code for free unmanaged and managed code.

This is why we need the Dispose function. All freeing up memory is not automatic, as you said in unmanaged code.

Now, if you think that unmanaged code is automatically released by the OS, it is not. There are many handles and locks that can remain active if you incorrectly place the application.

0
source share

First of all, I would like to note that IDisposable does not apply only to objects of the Windows kernel or unmanaged memory. Rather, it is something that garbage collection does not understand (of which kernel objects are a special case).

A small example, just to give you an idea:

  sealed class Logger : IDisposable { private bool _disposed = false; public Logger() { System.IO.File.AppendAllText( @"C:\mylog.txt", "LOG STARTED" ); } ~Logger() { Dispose(); } public void Dispose() { if ( !_disposed ) { System.IO.File.AppendAllText( @"C:\mylog.txt", "LOG STOPPED" ); _disposed = true; } } public void WriteMessage( string msg ) { System.IO.File.AppendAllText( @"C:\mylog.txt", "MESSAGE: " + msg ); } } 

Note that this Logger class does not “hold” all core-type resources. He opens the file and closes it immediately. However, there is such a logic that when destroying an object, it should write "LOG STOPPED". This logic is something that the GC cannot understand - and this is the place to use IDisposable .

Therefore, you cannot expect to clean up Windows kernel objects after you. Perhaps something else does not know Windows.

However, provided that your disposable objects are correctly written (i.e., by calling Dispose in the finalizer), they will still be deleted by the CLR after the process is complete.

So, the answer is: yes, you do not need to call Dispose immediately before the project exit. But NOT because one-time resources are kernel objects (because they are not necessarily there).


Edit

As Josh Einstein correctly pointed out, finalizers are not really guaranteed to work at the output of the process. So then the answer will be: always call Dispose, just to file a lawsuit

0
source share

All Articles