NullReferenceException背后的设计决策是什么,除了基类数据(如stacktrace)外,不包含任何运行时特定的信息?Visual Studio是否有扩展程序可以立即告诉您表达式的哪一部分为空?
NullReferenceException背后的设计决策是什么,除了基类数据(如stacktrace)外,不包含任何运行时特定的信息?Visual Studio是否有扩展程序可以立即告诉您表达式的哪一部分为空?
Answers:
NRE是非常底层的异常。当要求处理器从低于64K的地址读取数据时,这是处理器生成的硬件异常(“陷阱”)。虚拟内存空间的该区域始终未映射,专门用于捕获指针错误。它以AccessViolation开头,当地址小于0x00010000时由CLR变为NRE。那时,异常的上下文很少,所知道的只是引起陷阱的机器代码指令的地址。
无法将机器代码指令地址反向工程回程序中的命名变量。重要的是,它的工作原理是这样,抖动就必须产生非常否则低效的代码。可以合理地做的就是恢复源代码行号。这需要包含行号信息的调试信息(.pdb)。CLR知道如何读取.pdb文件,并使用它来生成异常的堆栈跟踪。但是,由于JIT优化器执行的优化,这通常仍然不准确,会四处移动代码。您只会获得与Debug构建版本匹配的保证。Release版本的PDB不包含源行号信息的原因。您可以更改它。
这个问题有一个非常简单的解决方案。自己检查null并生成自己的异常,然后再让运行时执行。该测试非常便宜,不到一纳秒。
null发生NRE时的表达式。知道到底怎么可能吗?blogs.msdn.microsoft.com/dotnet/2016/08/02/...
您可以将Visual Studio设置为NullReferenceException立即抛出,而不是首先在catch块中断。
然后,您将在导致的行中中断NullReferenceException。
没有简单的方法可以确定运行时为空的内容–必须从IL中反编译并推断必要的信息,该信息足够低级,它所知道的只是“堆栈顶部的项目为空” ”,但该物品如何到达那里。
(而且我不知道这样的扩展,但这将是一个不错的调试器增强)
并非有关代码的所有信息都在运行时可用。例如,本地变量名称不可用。因此,不可能抛出类似“本地变量myObj为空,但其成员已被调用”之类的消息的异常。此外,在运行时还有许多非用户编写的对象(例如,为闭包/匿名类型/迭代器等生成的类),它们也可能是null引用异常的来源。
如果有调试符号,则可以跟踪引起异常的行。如果足够简单,那么您将直接获得null价值。否则(请考虑a.Value = b.Do(c.GetX(),d.GetY(z.ToString()));),您必须使用IDE进行调试