Incorrect stacktrace by rethrow
Throwing twice in the same method is probably a special case - I've not been able to create a stack trace where different lines in the same method follow each other. As the word says, a "stack trace" shows you the stack frames that an exception traversed. And there is only one stack frame per method call!
If you throw from another method, throw;
will not remove the entry for Foo()
, as expected:
static void Main(string[] args)
{
try
{
Rethrower();
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
Console.ReadKey();
}
static void Rethrower()
{
try
{
Foo();
}
catch (Exception ex)
{
throw;
}
}
static void Foo()
{
throw new Exception("Test");
}
If you modify Rethrower()
and replace throw;
by throw ex;
, the Foo()
entry in the stack trace disappears. Again, that's the expected behavior.
Rethrow an Exception with correct line numbers in the stack trace
You do not lose original exception if you place it in an inner exception.
[WebMethod]
public void ExceptionTest()
{
try
{
throw new Exception("An Error Happened");
}
catch (Exception ex)
{
evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
throw new Exception("Your message", ex);
}
}
throw; is said to not reset stack trace, but it does in certain circumstances
As Darin already point out the reduced stack trace is due to method inlining. However there is also the point of the line reference that is available in the stack trace not being equal.
I do not know the explanation behind this, but there is a way for you to keep all stacktrace information when rethrowing an exception. You need to throw a new exception and pass the one you catch as the inner exception. With this approach the merged stacktrace will contain the point of origin of the exception and also the point where the exception is rethrown.
I talked about this and presented full examples on different ways to rethrow exceptions in the following blog post:
.NET Exceptions – throw ex is evil but throw is not that innocent
Your comment motivated me for a quick research but the best I could find was this comment by Jonathan de Halleux on a blog post about catch and rethrow:
It also changes the line number in the stacktrace in the method that
rethrows (since the rethrow becomes the site of throw in that method).
This could be elaborated further, but it points to the fact that probably the throw site which will then be used to obtain line information is tracked at each method and the rethrow causes it to be overridden.
So even though the stacktrace is preserved when using throw
instead of throw e
the original throw site will be lost unless you wrap and throw a new exception.
Other things to try; since SO does not allow direct messages and the above comment was made by Peli you can try to tag this question with pex
to get his attention and get him to follow up on that comment. :)
How to rethrow InnerException without losing stack trace in C#?
In .NET 4.5 there is now the ExceptionDispatchInfo
class.
This lets you capture an exception and re-throw it without changing the stack-trace:
using ExceptionDispatchInfo =
System.Runtime.ExceptionServices.ExceptionDispatchInfo;
try
{
task.Wait();
}
catch(AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
This works on any exception, not just AggregateException
.
It was introduced due to the await
C# language feature, which unwraps the inner exceptions from AggregateException
instances in order to make the asynchronous language features more like the synchronous language features.
Rethrowing exceptions in Java without losing the stack trace
catch (WhateverException e) {
throw e;
}
will simply rethrow the exception you've caught (obviously the surrounding method has to permit this via its signature etc.). The exception will maintain the original stack trace.
How can I rethrow an Inner Exception while maintaining the stack trace generated so far?
It is possible to preserve the stack trace before rethrowing without reflection:
static void PreserveStackTrace (Exception e)
{
var ctx = new StreamingContext (StreamingContextStates.CrossAppDomain) ;
var mgr = new ObjectManager (null, ctx) ;
var si = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;
e.GetObjectData (si, ctx) ;
mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData
mgr.DoFixups () ; // ObjectManager calls SetObjectData
// voila, e is unmodified save for _remoteStackTraceString
}
This wastes a lot of cycles compared to InternalPreserveStackTrace, but has the advantage of relying only on public functionality. Here are a couple of common usage patterns for stack-trace preserving functions:
// usage (A): cross-thread invoke, messaging, custom task schedulers etc.
catch (Exception e)
{
PreserveStackTrace (e) ;
// store exception to be re-thrown later,
// possibly in a different thread
operationResult.Exception = e ;
}
// usage (B): after calling MethodInfo.Invoke() and the like
catch (TargetInvocationException tiex)
{
PreserveStackTrace (tiex.InnerException) ;
// unwrap TargetInvocationException, so that typed catch clauses
// in library/3rd-party code can work correctly;
// new stack trace is appended to existing one
throw tiex.InnerException ;
}
rethrow exception preserving backtrace
With your script:
backtrace
quit
... you will only see a stack trace when the inferior is about to exit (or when you use a core file, like in your example, when it has already exited), because you have not told gdb to stop anywhere.
Another approach would be to use the gdb catch throw
command, plus a bit of scripting. This way you could capture a stack trace at each throw
. You could do it this way:
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
> silent
> backtrace
> continue
> end
This will stop at every throw
and print a backtrace. However, you did want to not print stack traces from the fatal
frame. For this, you could use a gdb convenience function and make the catchpoint conditional:
(gdb) cond 1 $_any_caller_matches("fatal", 10)
(The "10" is just a guess at how many frames may separate fatal
from the C++ library innards that handle throwing.)
Related Topics
Remove the Title Bar in Windows Forms
How to Write Super-Fast File-Streaming Code in C#
Casting Object to Int Throws Invalidcastexception in C#
Entity-Framework Code Is Slow When Using Include() Many Times
How to Get the Location of the Dll Currently Executing
How to Mock Out a .Net Httpwebresponse
Jobject.Parse VS JSONconvert.Deserializeobject
How to Find the Fully Qualified Name of an Assembly
How to Get Status Code from Webclient
C# Reflection - Load Assembly and Invoke a Method If It Exists
Change the Value in App.Config File Dynamically
Register Background Task in Silverlight 8.1 App
Limit the Number of Parallel Threads in C#
Convert Transparent Png to Jpg with Non-Black Background Color