.net中的空引用异常

时间:2010-05-28 18:42:28

标签: .net wpf

我们的应用程序遇到了这个大问题。它是一个相当大的应用程序,包含几个模块,以及成千上万行代码。应用程序的很多部分只是存在于另一个对象的引用中,例如,如果没有House对象,Person对象永远不会存在,所以如果你在应用程序的任何一点说:

bool check = App.Person.House == null;

check应始终为false(按设计),因此,为了继续使用该示例,在创建模块,测试,调试时,App.Person.House永远不会为null,但一旦我们发货对于我们的客户端的应用程序,他们开始得到一堆NullReferenceException与设计的对象,永远不应该有一个空引用。他们告诉我们这个错误,我们尝试在这里重现它,但是90%的时间我们都不能,因为这里工作正常。

该应用程序正在使用C#和WPF进行开发,并且在设计上,它仅在Windows XP SP 3和.net框架v3.5上运行,因此我们知道用户具有相同的操作系统,服务包和我们这里做的.net框架版本,但他们仍然得到我们无法重现的这个奇怪的NullReferenceExceptions

所以,我只是想知道是否有人以前见过这个以及你如何修复它,我们让这个应用程序在5台不同的计算机上每天运行至少8小时,我们从来没有看到这些异常,这只发生在客户出于某种原因。

任何想法,任何线索,任何可以让我们更接近解决这个问题的解决方案将不胜感激。

谢谢!

5 个答案:

答案 0 :(得分:10)

嗯,你还没有真正告诉我们很多关于众议院的财产......它是否可写?如果是这样,将验证放入至少的setter中,如果值为null,则理想情况下立即抛出ArgumentNullException(我认为通常最好在数据损坏时停止而不是继续并希望生活能够解决问题。如果它只是在构造函数中设置为支持字段,请在那里检查 - 如果它为空,则再次抛出ArgumentNullException

如果以某种方式计算,那就更难了 - 在这一点上你应该在getter和log中测试(以某种方式让你的客户很容易将信息传回给你)。你认为可能是相关的。

编辑:正如已经指出的那样,这可以适用于表达式中的任何级别 - 因此您可能希望对每个级别应用相同类型的验证和日志记录。

答案 1 :(得分:6)

该行

 bool check = App.Person.House == null;
AppApp.Person为空时,

将抛出null-ref异常。

你说'设计不能为空'但是无法从你的描述中验证。很明显,用户只需遵循程序中未包含在测试用例中的路径即可。

如果您无法发现设计中的缺陷,那么实际的方法是通过内部检查来扩展您的应用。我会推荐一个好的跟踪系统和(很多)System.Diagnostics.Trace.Assert(xx != null);

答案 2 :(得分:0)

如何实例化对象?可能是Person对象是null吗?甚至App对象?这可以解释例外情况。

如果找不到问题,我建议您将日志记录添加到应用程序,并检查实例化对象的代码以及使用它的代码是否在创建对象之前以某种方式访问​​对象。

另一个可能的问题可能是异常处理。确保你没有只吞下异常的try-catch块。这些可能是一些真正头痛的根源。

反正。这些只是建议。如果不了解您的系统,就很难做出更好的猜测。

答案 3 :(得分:0)

一个非常初步的猜测是你已经编码了yr而没有一致的异常处理模式,并且正在抛出一些其他异常并被不适当地吞下,这允许执行线程到达运行代码的点,该代码假定对象具有实例化后,实际上先前吞下或忽略的异常已经阻止它被实例化,并导致它仍然为空。

答案 4 :(得分:0)

如果不了解代码,猜测为什么会发生这种情况真的很难。典型的来源是

  • 访问unitialized值(左侧为默认值null),但通常C#编译器会发出警告
  • 当对象是意外类型时,
  • 强制转换(对象为Type),这些通常在早期测试中很快找到,除非你有一个完全未经测试的代码路径
  • 分配失败。在CLR中虽然它们引发了OutOfMemoryException
  • 数据库读取。这些很可能是原始值的罪魁祸首,但不适用于复杂的类。虽然ORM层可能会掩盖错误并简单地将空值分配给成员,从而触发您稍后会看到的错误
  • 逻辑错误。另一个可能的罪魁祸首,客户端使用该应用程序的方式会执行不同的代码路径,而这些路径根本不会分配值

当我遇到类似的问题时,我最终在应用程序中添加了检测。主要是记录(在我的案例中为log4net)和异常报告。最初我使用Assert,但CLR断言是生产中的灾难,因为它们弹出需要用户交互的大中断消息框,完全不适合服务和后台运行的应用程序。所以我更喜欢捕获异常,从异常上下文创建报告,并将报告发送回母舰进行分析。最终,我能够从这些例外报告中找出所有问题。我最终在http://bugcollect.com处围绕这个概念构建了一个服务,并将其与log4net集成,因此我可以从我的应用程序的所有部署(来自所有客户端)实时获取报告。