Solved

throw - reset or not reset stack trace

Posted on 2008-10-14
9
1,050 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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
 
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

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

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

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
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…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

730 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