函数返回时的 NullReferenceException

Jef*_*man 3 c# weak-references

运行我的多线程应用程序时,我收到 NullReferenceException,但仅当我在调试器之外以 Release 模式运行时。堆栈跟踪被记录下来,它总是指向同一个函数调用。我在函数中放置了几个日志语句来尝试确定它会到达多远,并且每个语句都会被记录,包括函数最后一行的一个。有趣的是,当 NullReferenceException 发生时,函数调用后的语句不会被记录:

    // ...
    logger.Log( "one" );  // logged
    Update( false );
    logger.Log( "eleven" );  // not logged when exception occurs
}

private void Update( bool condition )
{
    logger.Log( "one" );  // logged
    // ...  
    logger.Log( "ten" );  // logged, even when exception occurs
}
Run Code Online (Sandbox Code Playgroud)

每次调用函数时都不会发生异常。是否有可能在函数执行之前或期间堆栈被破坏,从而导致返回地址丢失,从而导致空引用?我不认为在 .NET 下这种事情是可能的,但我想更奇怪的事情发生了。

我尝试用函数的内容替换对函数的调用,所以一切都内联发生,然后异常发生在如下所示的行上:

foreach ( ClassItem item in classItemCollection )
Run Code Online (Sandbox Code Playgroud)

我已经通过日志验证“classItemCollection”不为空,并且我还尝试将 foreach 更改为 for 以防 IEnumerator 正在做一些有趣的事情,但异常发生在同一行上。

关于如何进一步调查的任何想法?

更新:一些响应者提出了与确保记录器不为空有关的可能解决方案。需要明确的是,在异常开始发生后,出于调试目的添加了日志记录语句。

Jef*_*man 5

我找到了我的空引用。就像 Fredrik 和 micahtan 所建议的那样,我没有为社区提供足够的信息来找到解决方案,所以我想我应该发布我的发现来解决这个问题。

这是正在发生的事情的代表:

ISomething something = null;

//...

// the Add method returns a strong reference to an ISomething
// that it creates.  m_object holds a weak reference, so when
// "this" no longer has a strong reference, the ISomething can
// be garbage collected.
something = m_object.Add( index );

// the Update method looks at the ISomethings held by m_object.
// it obtains strong references to any that have been added,
// and puts them in m_collection;
Update( false );

// m_collection should hold the strong reference created by 
// the Update method.
// the null reference exception occurred here
something = m_collection[ index ];

return something;
Run Code Online (Sandbox Code Playgroud)

问题原来是我使用“某物”变量作为临时强引用,直到 Update 方法获得永久引用。编译器在发布模式下优化掉“something = m_object.Add();” 分配,因为在再次分配之前不会使用“某物”。这允许 ISomething 被垃圾收集,因此当我尝试访问它时它不再存在于 m_collection 中。

我所要做的就是确保在调用 Update 之前保持强引用。

我怀疑这对任何人都有用,但如果有人好奇,我不想让这个问题悬而未决。