Solved

throw - reset or not reset stack trace

Posted on 2008-10-14
9
1,044 Views
Last Modified: 2013-12-17
Can one of you gurus please clear this up - all the documentation I can find clearly says that throw; resets the stack trace, but that doesn't seem to be the case:

class Program {
        static void Main(string[] args) {
            try {
                int i = 4;
                string str = "";
                throw new Exception("Hello World");
            } catch {
                int ignore = 3;
                throw;
            }
        }
    }

In this case the stack trace clearly points to throw; and not to the original throw new Exception("...");

Is this documented anywhere?  Is there an explanation for this?

AJR
0
Comment
Question by:ARACK04
  • 5
  • 3
9 Comments
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 22714332
throw just tells it to continue processing the stack in terms of finding an error handler (i.e. consider this to be unhandled still) it does not affect the stack trace at all. If you want to affect the stack trace use ...

        static void Main(string[] args) {
            try {
                int i = 4;
                string str = "";
                throw new Exception("Hello World");
            } catch(Exception Ex) {
                int ignore = 3;
                throw new Exception(Ex);
            }
        }
    }

which will rethrow the exception.

or even better use ...

static void Main(string[] args) {
            try {
                int i = 4;
                string str = "";
                throw new Exception("Hello World");
            } catch(Exception Ex) {
                int ignore = 3;
                throw new WhateverException("failed", Ex); //include the original exception as the inner exception
            }
        }
    }
0
 

Author Comment

by:ARACK04
ID: 22714699
With the original example, when I used throw; the line of the original throw new Exception("Hello World"); was completely absent.

The best I could find to explain this is  http://blogs.msdn.com/jmstall/archive/2007/02/07/catch-rethrow.aspx  and like you, he says that the error goes unhandled.

I'm just looking for some official MSDN documentation that explains this - everything I've found says that throw; maintains the stack trace, which doesn't seem to be the case.  Does maintain the stack trace mean something *different* from "view the line of the original exception"?

Thanks!
0
 
LVL 6

Assisted Solution

by:ebosscher
ebosscher earned 100 total points
ID: 22716017
Maybe i'm missing the point of the question?  The throw statement, according to MSDN (http://msdn.microsoft.com/en-us/library/0yd65esw(VS.71).aspx) is designed to rethrow an exception caught in an empty catch block (it's the only reason to use it).  As for resetting the stack trace, it did that?  It replaced (or reset) the stack trace to where you re-threw the exception.

If you want to PRESERVE the stack trace you will need to use catch(Exception ex) and then throw a new exception using ex as your inner exception.
0
 

Author Comment

by:ARACK04
ID: 22716541
A lot of stuff online states (incorrectly) that throw; preserves the stack trace, where throw e; does not (regardless of what, if anything, you're catching).

I was just looking for

a) some MSDN documentation that explains this, or
b) an explanation of what "preserve the stack trace" means, since throw; does definitely reset the text of the exception's stack trace that gets bubbled up.

The article you sent does not discuss the stacktrace property.  
Sorry if this was a poor question.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 37

Accepted Solution

by:
gregoryyoung earned 400 total points
ID: 22716591
from ECMA 335 section 4.24

Description:
The rethrow instruction is only permitted within the body of a catch handler (see Partition I). It throws the
same exception that was caught by this handler. A rethrow does not change the stack trace in the object.
Exceptions:
The original exception is thrown.
Correctness:
Correct CIL uses this instruction only within the body of a catch handler (not of any exception handlers
embedded within that catch handler). If a rethrow occurs elsewhere, an exception will be thrown, but
precisely which exception, is undefined
Verifiability:
There are no additional verification requirements.




Rethrow simply rethrows the same exception object. The stack trace is a part of that object, if you want a *new* stack trace you need a *new* object. Your original example is wrong if I am reading what you are saying correctly.

Here is an example to show you ...

namespace ConsoleApplication1
{
    class DoesException
    {
        private void privatemethod()
        {
            throw new ArgumentNullException("test");
        }
        public void publicmethod()
        {
            try
            {
                privatemethod();
            } catch (Exception Ex)
            {
                Console.WriteLine("catching in public\n" + Ex.ToString());
                throw;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DoesException d = new DoesException();
            try
            {
                d.publicmethod();
            }
            catch (Exception Ex)
            {
                Console.WriteLine(Ex.ToString());
            }
        }
    }
}


both print the same thing ...

Cheers,

Greg
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 22716659
Ah I see from your linked post that you are looking at how the *debugger* behaves.

The specification is talking about the stack trace in the exception itself not how a debugger will handle things.


Mike Stall is talking about how the debugger handles things.

Cheers,

Greg
0
 

Author Comment

by:ARACK04
ID: 22716967
No, you were right the first time - I was talking about the stack trace object.

I ran your code, and the two outputs were indeed different:

catching in public
System.ArgumentNullException: Value cannot be null.
Parameter name: test
   at ConsoleApplication1.DoesException.privatemethod() in C:\Users\Adam\Desktop
\junk\ConsoleApplication1\Program.cs:line 7
   at ConsoleApplication1.DoesException.publicmethod() in C:\Users\Adam\Desktop\
junk\ConsoleApplication1\Program.cs:line 11


System.ArgumentNullException: Value cannot be null.
Parameter name: test
   at ConsoleApplication1.DoesException.privatemethod() in C:\Users\Adam\Desktop
\junk\ConsoleApplication1\Program.cs:line 7
   at ConsoleApplication1.DoesException.publicmethod() in C:\Users\Adam\Desktop\
junk\ConsoleApplication1\Program.cs:line 14
   at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Adam\Desktop\j
unk\ConsoleApplication1\Program.cs:line 22
0
 

Author Comment

by:ARACK04
ID: 22826014
Well no sense in keeping this question open, so I may as well doll out some points.  The two stack traces were indeed different, and if anyone knows why, or has an explanation why they should be, please share the love :)
0
 

Author Comment

by:ARACK04
ID: 23912335
If anyone stumbles upon this question, here's some interesting info.  I had the opportunity to talk with an architect from Microsoft, and posed this question to him.  He seemed to know exactly where I was going before I finished it, and he told me point blank that re-throwing an exception does indeed change the stack trace, and that the MSDN docs that say otherwise were wrong.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now