Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

throw; is said to not reset stack trace, but it does in certain circumstances [duplicate]

Tags:

c#

.net

Possible Duplicate:
incorrect stacktrace by rethrow

It is generally accepted that in .NET throw; does not reset the stack trace but throw ex; does.

However, in this simple program , I get different line numbers:

void Main()
{
    try
    {
        try
        {
            Wrapper(); // line 13
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
            throw; // line 18
        }
    }
    catch(Exception e)
    {
          Console.WriteLine(e.ToString());
    }
}

public void Wrapper()
{
    Throw(); // line 28
}

public void Throw()
{
    var x = (string)(object)1; // line 33
}

The output is:

System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. at ConsoleApplication2.Program.Main(String[] args) in C:\long-path\Program.cs:line 13

System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. at ConsoleApplication2.Program.Main(String[] args) in C:\long-path\Program.cs:line 18

Note: The first stack trace contains line 13, the second contains line 18. Additionally, neither line 13 nor line 18 are the lines where the cast is actually happening.

My question now is: In what circumstances does throw; change the stack trace and in which circumstance doesn't it change the stack trace?

Please note, that this has already been observed, but not answered in general.


UPDATE:
I ran the code above in Debug mode and it yields this:

System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. at ConsoleApplication2.Program.Throw() in C:\long-path\Program.cs:line 33 at ConsoleApplication2.Program.Wrapper() in C:\long-path\Program.cs:line 28 at ConsoleApplication2.Program.Main(String[] args) in C:\long-path\Program.cs:line 13

System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. at ConsoleApplication2.Program.Throw() in C:\long-path\Program.cs:line 33 at ConsoleApplication2.Program.Wrapper() in C:\long-path\Program.cs:line 28 at ConsoleApplication2.Program.Main(String[] args) in C:\long-path\Program.cs:line 18

Please note: The last line number still changes

like image 706
Daniel Hilgarth Avatar asked Sep 11 '12 15:09

Daniel Hilgarth


1 Answers

The reason for this happening is because of method inlining when running in Release mode. If you don't want the Wrapper and Throw methods to be inlined in Release mode you could decorate them with the [MethodImpl] attribute:

[MethodImpl(MethodImplOptions.NoInlining)]
public void Wrapper()
{
    Throw();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public void Throw()
{
    var x = (string)(object)1;
}
like image 50
Darin Dimitrov Avatar answered Nov 15 '22 17:11

Darin Dimitrov