13

I found out that if I am catching an Exception e, e.innerException could possibly be null.

Is it also possible that e.StackTrace could also be null in any possible circumstance in a catch block?

try {

}
catch(Exception e)
{
//can e.StackTrace be null here?
}
Henley
  • 21,258
  • 32
  • 119
  • 207
  • I would say yes: http://stackoverflow.com/questions/5620678/nullreferenceexception-no-stack-trace-where-to-start http://stackoverflow.com/questions/6783561/nullreferenceexception-with-no-stack-trace-when-hooking-setconsolectrlhandler – Aaron Palmer Feb 10 '14 at 22:01

4 Answers4

18

Yes.

If you create a new Exception() and don't throw it, every property except Data and Message will be null.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
4

An example that proves the StackTrace can be null in a catch block is equally trivial to show:

public class DerpException : Exception
{
    public override string StackTrace
    {
        get { return null; }
    }
}
Preston Guillot
  • 6,493
  • 3
  • 30
  • 40
  • 4
    I'm actually shocked that `StackTrace` is virtual, simply because derived classes *shouldn't* be able to do something like this. – Servy Feb 10 '14 at 22:04
  • Looking in dotPeek, the property is actually defined in the `System.Runtime.InteropServices._Exception` interface, which explains why it's virtual in the base `System.Exception` class - the reasons for this interface are out of my reach as a lowly purveyor of purely managed code though. – Preston Guillot Feb 11 '14 at 01:04
  • 1
    The `Exception` class could still mark it as `sealed`, preventing *further* overrides of that property. – Servy Feb 11 '14 at 14:11
  • Sealing `Exception` would prevent *any* kind of more specific exception class from existing though. Inheriting the field from an interface doesn't force it to be implemented as `virtual` in the base `Exception` class either though, it just has to be `public`; I was brain dead at that point yesterday. – Preston Guillot Feb 11 '14 at 15:20
  • 1
    You can seal that property (or a method) without sealing the whole class. That's what I suggested. – Servy Feb 11 '14 at 15:21
  • 1
    I misread initially, but you don't even need to do that since methods aren't virtual by default in C#, you just need to *not* have the method be marked virtual, which is back to the original point. It seems like a deliberate design decision, and a really odd one. – Preston Guillot Feb 11 '14 at 15:37
0

It's possible to get exception.StackTrace as a null, if you use [HandleProcessCorruptedStateExceptions] attribute for your function with try-catch, where you catch exception, and if exception is thrown from native code.

System.AccessViolationException exception type might have StackTrace as null.

Not sure if this has anything to do with Debug/Release build and/or generated pdb files. I've observes this kind of crash for Release build.

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
0

I encountered a case where the exception had a Message, but the mere access of StackTrace threw an exception!

This worth repeating: Just accessing the StackTrace threw an exception, i.e. without even calling a method upon it (like ex.StackTrace.ToString()).

This happened when working with COM libraries.

Specifically, it happened when a .NET Framework dll referenced an interop dll. For some reason the clr couldn't find and load that interop dll, and the exception thrown was a normal System.IO.FileNotFoundException, which had a Message.

But, accessing its StackTrace itself threw an exception with the following stack trace:

System.Signature.GetSignature(Void* pCorSig, Int32 cCorSig, RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType)\r\n   at
System.Reflection.RuntimeMethodInfo.FetchNonReturnParameters()\r\n   at  
System.Reflection.RuntimeMethodInfo.GetParameters()\r\n   at   
System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)\r\n   at   
System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)\r\n   at  
System.Exception.GetStackTrace(Boolean needFileInfo)\r\n   at  
System.Exception.get_StackTrace()
OfirD
  • 9,442
  • 5
  • 47
  • 90