tags:

views:

167

answers:

5

Possible Duplicates:
Conditions when finally does not execute in a .net try..finally block
In C# will the Finally block be executed in a try, catch, finally if an unhandled exception is thrown ?

At http://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java#Finally_Blocks_and_Uncaught_Exceptions

Says that finally block dont runs always. Its wrong, right?

The ECMA standard for the CLI (from which C# derives its exception features) states that exceptions are handled in a two-pass search of the stack.[13] The first pass attempts to locate a matching catch block, and terminates the program if none is found. Only if a matching catch block is found does the second pass execute, which runs the intervening finally blocks. This allows the problem to be diagnosed without the program state first being modified by the finally blocks; it also eliminates the risk that finally blocks may have undesirable side-effects when the program is in an unknown state (such as corruption of external data, or throwing further exceptions).

But, i dont need a catch to finally executes

    static void Main()
    {
        try { throw new Exception(); }
        finally
        {
            Console.WriteLine("1");
        }
    }
A: 

It implies that if there's no catch clause anywhere on the stack, i.e. if the exception is unhandled, then the abend is immediate at the point at which the exception is thrown: even before any finally blocks can be run.

See C# Time of finally execution for further discussion and answers.

ChrisW
A: 

The finally statement will usually run, but as has been pointed out in one of (as far as I recall), TheDailyWTF.com's tales from the interview (http://thedailywtf.com/Articles/My-Tales.aspx), it doesn't always run.

I think (and I could be wrong on this), a StackOverflowException will not fall into a finally block. (The other lovely example that was posted in ThedailyWTF.com is a simple case of, the finally block won't run if the power is pulled ;)).

So, beware of believing that it will always run.

Furis
A: 

Don't forget that your assembly's main method is not the first method on the stack. There are several other methods (a mix of managed and unmanaged methods) below. These methods load your executing assembly, and finally call the main method with the command line arguments.

A typical call stack when debugging a managed application in Visual Studio looks like this:

MyProgram.exe!MyProgram.Program.Main(string[] args = {string[0]}) Line 15   C#
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

Somewhere on this call stack there might be a catch handler that prints the stack trace in case of an exception that has not been handled in user code. However, this is an implementation detail, and it doesn't conflict with section 12.4.2.5 of the specification.

0xA3
+1  A: 

Try this code, finally is never called:

    static void Main()
    {
        try {
            Environment.FailFast("failed");
        }
        finally
        {
            Console.WriteLine("1");
        }
    }
jmservera
AFAIK this is the only case when finally is never called.
Johannes Rudolph
@Johannes: StackOverflowException is also a candidate. Here finally is never executed: `static void Main(string[] args) { try { Main(null); } finally { Console.WriteLine("Finally"); } }`
0xA3
+4  A: 

I notice that no one has actually answered your question, which is "is this text correct?"

No, it is not correct, in that it omits an important point.

The relevant portion of the CLI specification which it fails to quote is section 12.4.2 of Partition I, which states:


A finally handler ... shall be executed whenever the block exits, regardless of whether that occurs by normal control flow or by an unhandled exception.


Now, as others have noted, there are some subtleties here. Notice that the specification clearly calls out that the finally is executed when the block exits. If the program is terminated by a failfast, by a stack overflow, or by someone pulling the power cord out of the wall, then the block never exits! The program could be terminated before the block exits, and therefore the finally would not run.

Eric Lippert
+1 Sensible and well-rounded answer, doesn't focus only on edge cases like many of the other answers.
John K
I'm reminded of magicFairyFinally blocks, which **always** run, even if the machine has no power. See http://thedailywtf.com/Articles/My-Tales.aspx
Brian
Thanks Eric. Actually I asked about the wikipedia text, and not if are cases where finally block is not executed.PS: Your blog is on my list of rss, and certainly is the best about C#. Maybe you dont remember, but I asked you about translate your Covariance series to portuguese some time ago
Fujiy