奇怪的 nullreference 异常

Strange nullreference exception

提问人:arul 提问时间:12/27/2008 最后编辑:arul 更新时间:12/28/2008 访问量:491

问:

因此,我有这段代码来处理来自远程计算机的命令确认,有时(例如每 14 天一次)以下行会引发空引用异常:

computer.ProcessCommandAcknowledgment( commandType );

真正让我烦恼的是,我在它之前检查了一个空引用,所以我不知道发生了什么。 以下是其价值的完整方法:

    public static void __CommandAck( PacketReader reader, SocketContext context )
    {
        string commandAck = reader.ReadString();

        Type commandType = Type.GetType( commandAck );

        Computer computer = context.Client as Computer;

        if (computer == null)
        {
            Console.WriteLine("Client already disposed. Couldn't complete operation");
        }
        else
        {
            computer.ProcessCommandAcknowledgment( commandType );
        }
    }

有什么线索吗?

编辑:ProcessCommandAcknowledgeledgment:

    public void ProcessCommandAcknowledgment( Type ackType )
    {
        if( m_CurrentCommand.GetType() == ackType )
        {
            m_CurrentCommand.Finish();
        }
    }
C# .NET NullReferenceException

评论

0赞 JaredPar 12/27/2008
您能否指定 1) 多线程(是/否)、2) CLR 版本和 3) 处理器体系结构
0赞 arul 12/27/2008
单线程 / 2.0.50727.1433 / x86
0赞 JaredPar 12/27/2008
您可以发布 ProcessCommandAcknwoldgement 的签名吗?
0赞 Mark Brackett 12/27/2008
你能发布异常的堆栈跟踪吗?

答:

2赞 tvanfosson 12/27/2008 #1

是否有可能返回 null?这将导致 GetType 失败。也许您收到了一个空包?或者,字符串可能与类型不匹配,因此 commandType 在以后使用时将为 null。ReadString()

编辑: 您是否在调用时检查过不为空?m_CurrentCommandProcessCommandAcknowledgment

评论

0赞 arul 12/27/2008
不,nullref 被抛出在我突出显示的行,数据包 100% 确定是有效和完整的。(哈希控制 + 它们已加密)。
0赞 arul 12/27/2008
除此之外,命令 acknowledge 方法永远不会抛出 nullref,因为它将给定类型与绑定到计算机的类型进行比较,因此实际上与 null 的比较是有效的。
0赞 arul 12/27/2008
代码的任何部分都不会将其设置为 null。在 ctor 中,它默认为 Command.Invalid。
4赞 JaredPar 12/27/2008 #2

根据您提供的信息,在该位置发生空引用似乎是不可能的。因此,下一个问题是“您如何知道特定行正在创建 NullReferenceException?是否正在使用调试器或堆栈跟踪信息?您是否正在检查代码的零售版本或调试版本?

如果是调试器,则各种设置组合实质上会导致调试器不同位置报告 NullRef。这样做的主要方法是“仅我的代码”设置。

根据我的经验,我发现确定异常实际发生的行的最可靠方法是......

  1. 关闭 JMC
  2. 使用 Debug 进行编译
  3. 调试器 -> 设置 -> 引发 CLR 异常时中断。
  4. 检查调试器窗口中的 StackTrace 属性

评论

0赞 arul 12/27/2008
我有一个 PDB 详细的堆栈跟踪。该信息是 100% 正确的。
2赞 nbevans 12/27/2008 #3

我敢打赌,你的TCP框架代码有问题(如果你有的话!

“PacketReader”可能表明您没有。因为,从技术上讲,如果你这样做,它将被称为“FrameReader”或类似的东西。

如果涉及的两台 PC 位于本地 LAN 或其他设备上,那么它可能会解释 14 天的间隔。如果您在互联网上尝试过,我敢打赌您的错误频率会更常见,尤其是在 WAN 带宽受到争议的情况下。

评论

0赞 arul 12/27/2008
无效数据包将被丢弃,发送它们的客户端将断开连接。首先检查有效负载的 crc,然后解压缩数据包,最后解密。如果这些步骤中的任何一个失败,客户端将断开连接。
1赞 leppie 12/27/2008 #4

如果您打开了优化,它可能会将您指向一个非常错误的地方,而实际发生它。

几年前,类似的事情发生在我身上。

评论

0赞 arul 12/27/2008
好吧,它一直在可靠地使用相同的编译器设置。始终指向出错的位置。只有在这种特殊情况下,似乎才有问题。
1赞 Joshua 12/27/2008 #5

否则,可能在上下文被另一个线程设置为 null 的某个地方发生线程争用。这也可以解释这种错误的不常见性。

1赞 Charlie Martin 12/27/2008 #6

好吧,这真的只有几种可能性。

  1. 不知何故,当您调用该例程时,您的计算机引用被踩踏了。

  2. 调用下的某些内容引发了空指针取消引用错误,但在该行检测到该错误。

看着它,我非常怀疑堆栈正在损坏,导致您的自动系统被破坏。检查你遇到问题的子程序/方法/函数调用周围的子程序/方法/函数调用;特别是,请检查您制作成“计算机”项目的内容是否确实是您期望的类型。computer

评论

0赞 arul 12/27/2008
谢谢,有什么线索如何调试吗?
0赞 Charlie Martin 12/27/2008
这些可能很难调试。我会尝试两件事:(1) 在该位置捕获空引用异常,并在发生时获取尽可能多的信息;(2) grep 调用该例程的代码,并检查每个例程的代码。
0赞 Charlie Martin 12/27/2008
哦,在那个异常处理程序中,看看 Console.client 真正给你的东西。
1赞 Mark Brackett 12/27/2008 #7

其他线程在做什么?

编辑:您提到服务器是单线程的,但另一条评论表明这部分是单线程的。如果是这种情况,您仍然可能遇到并发问题。

我认为,这里的底线是,您要么遇到多线程问题,要么遇到 CLR 错误。你可以猜到我认为哪个更有可能。

评论

0赞 arul 12/28/2008
当然,还有十几个其他线程在做一些有用的事情,另一方面,网络代码是单线程的。此外,我正在使用一个局部变量,该变量在这一点上永远不会为空,除非 GC 或其他任何方法。
0赞 Mark Brackett 12/28/2008
@arul - 您的支持字段是否被宣布为易失性?您在设置该字段时是否锁定?可能会有稍微不那么明显的并发问题。
0赞 arul 12/29/2008
它是一个局部变量,存在于堆栈上,不能声明为可变变量。
0赞 Mark Brackett 12/29/2008
Context.Client 的支持字段可能需要是可变的。
0赞 arul 1/22/2009
将其宣布为易失性可能解决了问题,我的意思是,从那时起它就没有发生过。
1赞 FlySwat 12/27/2008 #8

计算机。过程命令确认( commandType );

您是否有调试符号可以单步执行此操作?

ProcessCommandAcknowledgement 可能会引发 null ref 异常,并冒泡。

评论

0赞 arul 12/27/2008
是的。除此之外,ProcessCommandAcknowledgement 接受 null 命令。