.NET exception caught is unexpectedly null

假如想象 提交于 2019-12-20 11:06:52

问题


See below for an explanation of what is going on

I have a really weird issue where the exception caught is null.

The code uses MEF and tries hard to report composition errors. Using the debugger I can see the exception being thrown (an InvalidOperationException) but when it is caught by the last catch block in the code below the ex variable is null. This is true both in the debugger and when executing the code normally.

static T ResolveWithErrorHandling<T>() where T : class
{
    try
    {
        IocContainer.Compose(Settings.Default.IocConfiguration);
        return IocContainer.Resolve<T>();
    }
    catch (ReflectionTypeLoadException ex)
    {
        // ... special error reporting for ReflectionTypeLoadException
    }
    catch (Exception ex)
    {
        // ex is null - that should not be possible!
        // ... general error reporting for other exception types
    }
    return null;
}

The code I have replaced with comments is really simple code to format the error message. Nothing strange going on there.

I have tried to alter the code to discover what effect that might have:

  • If I remove the first catch block (ReflectionTypeLoadException) the exception caught in the final catch block is no longer null.
  • If I catch another exception type in the first catch block the exception caught in the final catch block is no longer null.
  • If I add a catch block for InvalidOperationException as the first catch block the exception caught in that block is not null.
  • If I add a catch block for InvalidOperationException between the two catch blocks the exception caught in that block is null.

The project uses Code Contracts and the code generated by the compiler is post-processed to check the contracts. Unfortunately, I havn't figured out a way to get rid of this for testing purposes without performing major surgery on the project.

My current workaround is to not catch ReflectionTypeLoadException and instead branch on the type of ex in the general exception handler.

What could be the explanation for this "impossible" behavior? What is up with ReflectionTypeLoadException catch block?


Embarrassingly the exception is not null and it cannot be null per the C# standard 15.9.5.

However, using Code Contracts in a project can mess up the display of local variables in the debugger because the IL code generated by the compiler can be rewritten by Code Contracts so the final IL is slightly out of sync with the debug information. In my case the ex variable is displayed as null even it is not. The unfortunate nature of the error reporting taking place right before application termination meant that I believed the error reporting to not be called as a result of ex being null and ex.Message throwing a NullReferenceException inside my catch block. Using the debugger I was able to "verify" that ex was null, except it was actually not null.

My confusion was compounded by the fact that a catch block for ReflectionTypeLoadException seems to affect the debugger display issue.

Thanks to all who responded.


回答1:


Just ran into this same problem. I finally found out that I catched different exceptions with the same name, like you did:

catch (ReflectionTypeLoadException ex)
{
    // ... 
}
catch (Exception ex)
{
    // ex is not null!
    // ...
}

Both are named 'ex'. Changing one of both names solved this problem for me, like:

catch (ReflectionTypeLoadException reflectionEx)
{
    // ... 
}
catch (Exception ex)
{
    // ex is null - that should not be possible!
    // ...
}



回答2:


I ran in the same problem. In my case renaming the exception variable (e.g. ex => ex1) allowed to me to catch any exception...




回答3:


You should check if at some point, the IocContainer catches an Exception ex throws ex.InnerException without checking if it is null.

C# happily accepts throw null, and ends up in catch (Exception).




回答4:


I ran into the same problem. The exception was null when viewed in the debugger even though the correct type of exception - UpdateException - was being caught. I could view the exception by opening the Exception Assistant.

As soon as I turned off "Perform Runtime Contract Checking" caught exceptions where no longer null. I have been actively using code contracts for going on a year now and had not seen this problem before I starting working with EF 4.1 in this particular project recently - but I do not know if EF was a controlling variable in regards to caught exceptions being null.




回答5:


The exception is in fact not null, it's a problem with the debugger. Code contracts (ccrewrite) changes IL opcodes and that perturbates the debugger, because leave.s opcodes are transformed into leave opcodes. The two opcodes have different sizes and instruction adresses change, that's why the debugger is lost when exception names are the same.

You can use $exception in the debugger to workaround the issue.




回答6:


I have got the same situation, too. It happened to be a bug of Eclipse debugger. (Really, this situation can be only the result of some debugger's bug. )

Eclipse restart was enough - runtime exception becomes normal, not null. Other debuggers could be not so kind.



来源:https://stackoverflow.com/questions/5650868/net-exception-caught-is-unexpectedly-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!