我有一小段C ++代码让我疯了。每当它运行时,它会在非常意外的地方抛出一个空引用异常。
void CSoundHandle::SetTarget(CSound* sound)
{
assert(_Target == nullptr);
if (sound == nullptr) { return; }
_Target = sound;
// This works just fine.
_Target->Play();
// This is the code that throws the exception. It doesn't seem possible, as
// we should not be able to get here if 'sound' is null.
_Target->Stop();
}
那到底是怎么回事?输出窗口中的消息是:
this->_Target-> was nullptr.
0xC0000005: Access violation reading location 0x00000014
我已经在反汇编中确认它也没有在Stop函数内部发生。这怎么可能?
编辑: 确实初始化了声音的指针,并且这个'和' this->目标'是非空的。
编辑2: 我通过稍微改变Stop函数的声明以某种方式解决了这个问题:
// From this.
virtual void Stop();
// To this.
void Stop();
这似乎特别奇怪,因为Play()也是虚拟的,但是没有任何麻烦。我不能说我以前见过这样的事情。没有其他名为' Stop'在程序的其余部分,也没有CSound的子类,所以我有点困惑。
答案 0 :(得分:3)
读取位置0x00000014
意味着您正在尝试从对象的开头访问位于0x14字节的字段。指向该对象的指针设置为null。所以问题出在函数的调用者身上:它传递一个指向sound
的错误指针,它既不是null也不是有效的。这就是为什么函数中的空检查通过(0x14不为空),但你仍然崩溃。
更新:
对问题的第二次编辑表明问题在于调用虚函数。这里的null是虚拟指针,0x14是Stop
虚函数的偏移量。在对象构造期间设置虚拟指针(在编译器生成的代码中),并且永远不应该指向0.如果是,则程序的某些部分正在破坏对象。一个易于检测的情况是尝试重置对象,但内存损坏(例如,对数组的越界写入)也可能导致此问题。