Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1066
  • Last Modified:

throw - reset or not reset stack trace

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
ARACK04
Asked:
ARACK04
  • 5
  • 3
2 Solutions
 
gregoryyoungCommented:
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
 
ARACK04Author Commented:
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
 
ebosscherCommented:
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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
ARACK04Author Commented:
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
 
gregoryyoungCommented:
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
 
gregoryyoungCommented:
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
 
ARACK04Author Commented:
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
 
ARACK04Author Commented:
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
 
ARACK04Author Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now