Solved

throw - reset or not reset stack trace

Posted on 2008-10-14
9
1,045 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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …

911 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

22 Experts available now in Live!

Get 1:1 Help Now