I'm writing some exception handling best practices based on several sources in the web. From the Microsoft webpage (https://msdn.microsoft.com/en-us/library/seyhszts(v=vs.110).aspx) I got the recommendation:
"The stack trace begins at the statement where the exception is thrown and ends at the catch statement that catches the exception. Be aware of this fact when deciding where to place a throw statement."
I'm not really shure what this means. Can we say the best place for a 'throw' is as close to the call in question as possible? Is this correct or does anybody have other suggestions?
Edit: I will be more precise. See the following pseudo code below
// do something that assignes a value to 'someValue'
// do more that's not related to the call above
if (someValue == whatever)
{
throw new MyException();
}
I assume when I'm throwing the exception after doing something else after the call in question (do something), I will not get the correct stack trace pointing me to the right line. Am I right?
"The stack trace begins at the statement where the exception is thrown and ends at the catch statement that catches the exception. Be aware of this fact when deciding where to place a throw statement."
If the following code is not wrapped inside a try-catch block, the debugger would give you a stack trace where the topmost item points to the DivideTwoNumbers() function since it is where the exception has occurred. All other code after this line: double quotient = DivideTwoNumbers(10, 0); will not executed which means all other throw statements you have will be useless. Suppose you are expecting an exception inside AnotherFunction(), do you get to catch the exception or will AnotherFunction() be included in the stack trace? The answer is NO.
static void Main(string[] args)
{
try
{
double quotient = DivideTwoNumbers(10, 0);
AnotherFunction();
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
static int DivideTwoNumbers(int dividend, int divisor)
{
if (divisor == 0)
throw new DivideByZeroException();
return dividend / divisor;
}
Related
I have been playing around with Exceptions to learn more about how I should use them properly. So far, I know that throw keeps the original stack trace; throw new CustomException(...) is generally used when wanting to add more information about the exception that took place or add/change the message, or even change the type of Exception itself; and throw ex should never ever be used, unless I want to lose the original stack trace.
So I wrote a small program where I could catch and rethrow an exception several times while adding something to the original message.
public class Sample
{
static void Main(string[] args)
{
new Tester().FirstCall();
}
}
public class Tester
{
public void FirstCall()
{
try
{
SecondCall();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.Message);
}
}
public void SecondCall()
{
try
{
ThirdCall();
}
catch (GoodException ex)
{
throw new Exception(ex.Message, ex);
}
}
public void ThirdCall()
{
try
{
FourthCall();
}
catch (ArithmeticException ae)
{
throw new GoodException("Arithmetic mistake: " + ae.Message, ae);
}
}
public void FourthCall()
{
int d = 0;
int x = 10 / d;
}
}
Where GoodException is a custom exception implemented correctly.
I'm expecting the console to display something like this:
at PlayingWithExceptions.Tester.FourthCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 67
at PlayingWithExceptions.Tester.ThirdCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 59
at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.
But instead I'm getting this:
at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.
For some reason it only goes as far as the second call. Even though I'm passing the caught exception as an InnerException, the stack trace is still lost. I'm aware that if I just wrote throw instead of throwing a new exception, I could keep the original stack trace, but if I do that I won't be able to change the original message (which was the whole point of this exercise).
So my question is, what can I do to change the Exception message AND keep the original stack trace the whole way?
EDIT: Since an exception should not be used logic control and only caught once, the proper way to keep the original stack trace AND show the new message is to wrap the FourthCall in a try/catch (where the new Exception with its message is generated), and catch it only once all the way up in the FirstCall.
The stack trace isn't "lost" it's pushed into the InnerException, just like you told it to be. The "outer" exception in this case, did not participate in the call chain of the Inner exception - it's a brand new exception which originates in SecondCall, so that's the beginning of its stack trace.
And yes, the commenters are correct. To control your messaging, you won't do that by trying to set the message in the Exception object - Exceptions should be handled by code, messages are for users. So, you'll log the message, display it to the user, something like that.
Don't know if it still relevant for you. Just use the keyword "throw" without the exception append to it , then the trace will not be lost and the original exception will be throws. not as inner.
I am trying to learn how to debug and handle errors in C# code using VS2012 for Desktop. I am stepping-through the below code using the Step Into F11 technique.
I understand how the execution of code jumps between different parts of code. I have messages printed out to console to help me identify which step is being executed. I have split my screen so I can see which line of code I'm stepping into and the output messages in the console at the same time.
On line 70 (marked in the comments) - when the nested index is passed to the throwException() I do not understand why there is a throw keyword and what its functionality is. Why does the pointer jump to the nested finally block but then it goes back all the way to the main and throws IndexOutOfBounds exception. What does that mean? I see where the execution jump in the code but I don't understand why it just says throw. Does it mean that the exception is already handled? But how?
I read that when you throw an exception there is no need to add a break; statement because the switch statement breaks when it meets throw keyword, but I am not sure this is the right path of thinking in this example.
Please, help me understand the meaning of the throw keyword on line 70.
Thank you in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ch07Ex02
{
class Program
{
static string[] eTypes = { "none", "simple", "index", "nested index" };
static void Main(string[] args)
{
foreach (string eType in eTypes)
{
try
{
Console.WriteLine("Main() try block reached."); // Line 19
Console.WriteLine("ThrowException(\"{0}\") called.", eType);
ThrowException(eType);
Console.WriteLine("Main() try block continues."); // Line 22
}
catch (System.IndexOutOfRangeException e) // Line 24
{
Console.WriteLine("Main() System.IndexOutOfRangeException catch"
+ " block reached. Message:\n\"{0}\"",
e.Message);
}
catch // Line 30
{
Console.WriteLine("Main() general catch block reached.");
}
finally
{
Console.WriteLine("Main() finally block reached.");
}
Console.WriteLine();
}
Console.ReadKey();
}
static void ThrowException(string exceptionType)
{
Console.WriteLine("ThrowException(\"{0}\") reached.", exceptionType);
switch (exceptionType)
{
case "none":
Console.WriteLine("Not throwing an exception.");
break; // Line 50
case "simple":
Console.WriteLine("Throwing System.Exception.");
throw new System.Exception(); // Line 53
case "index":
Console.WriteLine("Throwing System.IndexOutOfRangeException.");
eTypes[4] = "error"; // Line 56
break;
case "nested index":
try // Line 59
{
Console.WriteLine("ThrowException(\"nested index\") " +
"try block reached.");
Console.WriteLine("ThrowException(\"index\") called.");
ThrowException("index"); // Line 64
}
catch // Line 66
{
Console.WriteLine("ThrowException(\"nested index\") general"
+ " catch block reached.");
throw; // Line 70
}
finally
{
Console.WriteLine("ThrowException(\"nested index\") finally"
+ " block reached.");
}
break;
}
}
}
}
The above code compiles and runs with no errors.
Keyword throw can be used all by itself inside a catch clause to rethrow whatever exception has been caught by that catch block. It lets you "plug in" some execution logic in the process of handling the exception without disrupting the details of where the exception has been thrown.
In this case, you are able to log the details to console, and then re-throw the exception as if you never handled it. Note that this is different from catching an exception and wrapping it in your own, because the details of the original exception are preserved.
throw; inside a catch says "I don't actually know what to do about this exception so let somebody else higher up the stack catch it (without me having modified it)."
The throw in question will re-throw the exception, such that the stack trace and other info is preserved.
Have a look at Rethrow to preserve stack details
Also from try-catch (C# Reference)
If you want to re-throw the exception currently handled by a
parameter-less catch clause, use the throw statement without arguments
catch
{
throw;
}
The throw keyword is used to re-throw caught exceptions without losing the correct stack trace. It is used to do some execution when the exception is caught (for example logging, as it is in your example).
Please see this: SO qeustion on rethrowing exceptions
and this: codinghorror blogpost (please note the clarifications in the comments)
I`m writing class. Here is one of functions:
public string GetAttribute(string attrName)
{
try
{
return _config.AppSettings.Settings[attrName].Value;
} catch(Exception e)
{
throw new ArgumentException("Element not exists", attrName);
return null;
}
}
Then, I am using it in the main form MessageBox.Show(manager.GetAttribute("not_existing_element"));
Visual Studio throws an Exception at line:throw new ArgumentException("Element not exists", attrName);
but, I am want to get an Exception at line MessageBox.Show(manager.GetAttribute("not_existing_element"));
How can I do that?
P.S: Sorry for bad English.
You are misusing exception handling. In your code, if you get (for example) a NullReferenceException, you will catch it and then throw an ArgumentException.
Rewrite your method to not have any exception handling:
public string GetAttribute(string attrName)
{
return _config.AppSettings.Settings[attrName].Value;
}
This way, you are not resetting the stack trace and swallowing the original exception.
In terms of getting an exception on the calling line - you will never be able to get an exception at a line that isn't throwing an exception.
A couple of things:
First, you'll get an unreachable code warning for the return null statement in your catch, because the throw will execute before the return. You can simply delete the return null statement.
Secondly, I'm not sure what you mean by getting the exception at the MessageBox line, but I think you mean you want to catch it there. Wrap the call to MessageBox in a try-catch.
try
{
MessageBox.Show(manager.GetAttribute("not_existing_element"));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I have this code
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
Code above is called in this code
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
The exception passed as parameter to the method "HandleException" contains the line number of the "throw" line in the stack trace instead of the real line where the exception was generated. Anyone knows why this could be happening?
EDIT1
Ok, thanks to all for your answers. I changed the inner catch for
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
Now I have the correct line on the stack trace, but I had to create a new exception. I was hoping to find a better solution :-(
EDIT2
Maybe (if you have 5 minutes) you could try this scenario in order to check if you get the same result, not very complicated to recreate.
Yes, this is a limitation in the exception handling logic. If a method contains more than one throw statement that throws an exception then you'll get the line number of the last one that threw. This example code reproduces this behavior:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new Exception(); // Line 15
}
catch {
throw; // Line 18
}
}
}
Output:
System.Exception: Exception of type 'System.Exception' was thrown.
at Program.Test() in ConsoleApplication1\Program.cs:line 18
at Program.Main(String[] args) in ConsoleApplication1\Program.cs:line 6
The work-around is simple, just use a helper method to run the code that might throw an exception.
Like this:
static void Test() {
try {
Test2(); // Line 15
}
catch {
throw; // Line 18
}
}
static void Test2() {
throw new Exception(); // Line 22
}
The underlying reason for this awkward behavior is that .NET exception handling is built on top of the operating system support for exceptions. Called SEH, Structured Exception Handling in Windows. Which is stack-frame based, there can only be one active exception per stack frame. A .NET method has one stack frame, regardless of the number of scope blocks inside the method. By using the helper method, you automatically get another stack frame that can track its own exception. The jitter also automatically suppresses the inlining optimization when a method contains a throw statement so there is no need to explicitly use the [MethodImpl] attribute.
"But throw; preserves the stack trace !! Use throw; "
How many times have you heard that... Well anyone who has been programming .NET for a while has almost certainly heard that and probably accepted it as the be all and end all of 'rethrowing' exceptions.
Unfortunately it's not always true. As #hans explains, if the code causing the exception occurs in the same method as the throw; statement then the stack trace gets reset to that line.
One solution is to extract the code inside the try, catch into a separate method, and another solution is to throw a new exception with the caught exception as an inner exception. A new method is slightly clumsy, and a new Exception() loses the original exception type if you attempt to catch it further up the call stack.
I found a better description of this problem was found on Fabrice Marguerie's blog.
BUT even better there's another StackOverflow question which has solutions (even if some of them involve reflection):
In C#, how can I rethrow InnerException without losing stack trace?
As of .NET Framework 4.5 you can use the ExceptionDispatchInfo class to do this without the need for another method. For example, borrowing the code from Hans' excellent answer, when you just use throw, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch {
throw; // Line 18
}
}
}
It outputs this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
But, you can use ExceptionDispatchInfo to capture and re-throw the exception, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch(Exception ex) {
ExceptionDispatchInfo.Capture(ex).Throw(); // Line 18
}
}
}
Then it will output this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 15
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
As you can see, ExceptionDispatchInfo.Throw appends additional information to the stack trace of the original exception, adding the fact that it was re-thrown, but it retains the original line number and exception type. See the MSDN documentation for more information.
Does the date/time stamp of your .pdb file match your .exe/.dll file? If not, it could be that the compilation is not in "debug mode" which generates a fresh .pdb file on each build. The pdb file has the accurate line numbers when exceptions occur.
Look into your compile settings to make sure the debug data is generated, or if you're in a test/production environment, check the .pdb file to make sure the timestamps match.
C# stack traces are generated at throw time, not at exception creation time.
This is different from Java, where the stack traces are filled at exception creation time.
This is apparently by design.
I often get this in production systems if Optimize code is checked.
This screws up line numbers even in 2016.
Make sure your configuration is set to 'Release' or whatever configuration you are building and deploying under. The checkbox has a different value per configuration
I never ultimately know how more 'optimized' my code is with this checked - so check it back if you need to - but it has saved my stack trace on many occasions.
What are the best practices to consider when catching exceptions and re-throwing them? I want to make sure that the Exception object's InnerException and stack trace are preserved. Is there a difference between the following code blocks in the way they handle this?
try
{
//some code
}
catch (Exception ex)
{
throw ex;
}
Vs:
try
{
//some code
}
catch
{
throw;
}
The way to preserve the stack trace is through the use of the throw; This is valid as well
try {
// something that bombs here
} catch (Exception ex)
{
throw;
}
throw ex; is basically like throwing an exception from that point, so the stack trace would only go to where you are issuing the throw ex; statement.
Mike is also correct, assuming the exception allows you to pass an exception (which is recommended).
Karl Seguin has a great write up on exception handling in his foundations of programming e-book as well, which is a great read.
Edit: Working link to Foundations of Programming pdf. Just search the text for "exception".
If you throw a new exception with the initial exception you will preserve the initial stack trace too..
try{
}
catch(Exception ex){
throw new MoreDescriptiveException("here is what was happening", ex);
}
Actually, there are some situations which the throw statment will not preserve the StackTrace information. For example, in the code below:
try
{
int i = 0;
int j = 12 / i; // Line 47
int k = j + 1;
}
catch
{
// do something
// ...
throw; // Line 54
}
The StackTrace will indicate that line 54 raised the exception, although it was raised at line 47.
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
at Program.WithThrowIncomplete() in Program.cs:line 54
at Program.Main(String[] args) in Program.cs:line 106
In situations like the one described above, there are two options to preseve the original StackTrace:
Calling the Exception.InternalPreserveStackTrace
As it is a private method, it has to be invoked by using reflection:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
I has a disadvantage of relying on a private method to preserve the StackTrace information. It can be changed in future versions of .NET Framework. The code example above and proposed solution below was extracted from Fabrice MARGUERIE weblog.
Calling Exception.SetObjectData
The technique below was suggested by Anton Tykhyy as answer to In C#, how can I rethrow InnerException without losing stack trace question.
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
}
Although, it has the advantage of relying in public methods only it also depends on the following exception constructor (which some exceptions developed by 3rd parties do not implement):
protected Exception(
SerializationInfo info,
StreamingContext context
)
In my situation, I had to choose the first approach, because the exceptions raised by a 3rd-party library I was using didn't implement this constructor.
When you throw ex, you're essentially throwing a new exception, and will miss out on the original stack trace information. throw is the preferred method.
The rule of thumb is to avoid Catching and Throwing the basic Exception object. This forces you to be a little smarter about exceptions; in other words you should have an explicit catch for a SqlException so that your handling code doesn't do something wrong with a NullReferenceException.
In the real world though, catching and logging the base exception is also a good practice, but don't forget to walk the whole thing to get any InnerExceptions it might have.
Nobody has explained the difference between ExceptionDispatchInfo.Capture( ex ).Throw() and a plain throw, so here it is. However, some people have noticed the problem with throw.
The complete way to rethrow a caught exception is to use ExceptionDispatchInfo.Capture( ex ).Throw() (only available from .Net 4.5).
Below there are the cases necessary to test this:
1.
void CallingMethod()
{
//try
{
throw new Exception( "TEST" );
}
//catch
{
// throw;
}
}
2.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch( Exception ex )
{
ExceptionDispatchInfo.Capture( ex ).Throw();
throw; // So the compiler doesn't complain about methods which don't either return or throw.
}
}
3.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch
{
throw;
}
}
4.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch( Exception ex )
{
throw new Exception( "RETHROW", ex );
}
}
Case 1 and case 2 will give you a stack trace where the source code line number for the CallingMethod method is the line number of the throw new Exception( "TEST" ) line.
However, case 3 will give you a stack trace where the source code line number for the CallingMethod method is the line number of the throw call. This means that if the throw new Exception( "TEST" ) line is surrounded by other operations, you have no idea at which line number the exception was actually thrown.
Case 4 is similar with case 2 because the line number of the original exception is preserved, but is not a real rethrow because it changes the type of the original exception.
You should always use "throw;" to rethrow the exceptions in .NET,
Refer this,
http://weblogs.asp.net/bhouse/archive/2004/11/30/272297.aspx
Basically MSIL (CIL) has two instructions - "throw" and "rethrow":
C#'s "throw ex;" gets compiled into MSIL's "throw"
C#'s "throw;" - into MSIL "rethrow"!
Basically I can see the reason why "throw ex" overrides the stack trace.
A few people actually missed a very important point - 'throw' and 'throw ex' may do the same thing but they don't give you a crucial piece of imformation which is the line where the exception happened.
Consider the following code:
static void Main(string[] args)
{
try
{
TestMe();
}
catch (Exception ex)
{
string ss = ex.ToString();
}
}
static void TestMe()
{
try
{
//here's some code that will generate an exception - line #17
}
catch (Exception ex)
{
//throw new ApplicationException(ex.ToString());
throw ex; // line# 22
}
}
When you do either a 'throw' or 'throw ex' you get the stack trace but the line# is going to be #22 so you can't figure out which line exactly was throwing the exception (unless you have only 1 or few lines of code in the try block). To get the expected line #17 in your exception you'll have to throw a new exception with the original exception stack trace.
You may also use:
try
{
// Dangerous code
}
finally
{
// clean up, or do nothing
}
And any exceptions thrown will bubble up to the next level that handles them.
I would definitely use:
try
{
//some code
}
catch
{
//you should totally do something here, but feel free to rethrow
//if you need to send the exception up the stack.
throw;
}
That will preserve your stack.
FYI I just tested this and the stack trace reported by 'throw;' is not an entirely correct stack trace. Example:
private void foo()
{
try
{
bar(3);
bar(2);
bar(1);
bar(0);
}
catch(DivideByZeroException)
{
//log message and rethrow...
throw;
}
}
private void bar(int b)
{
int a = 1;
int c = a/b; // Generate divide by zero exception.
}
The stack trace points to the origin of the exception correctly (reported line number) but the line number reported for foo() is the line of the throw; statement, hence you cannot tell which of the calls to bar() caused the exception.