6

我这里有一个奇怪的问题。假设我有一个带有一些虚拟方法的类。在某些情况下,此类的实例应调用其中一种方法。大多数时候那个阶段没有问题,但有时发现无法调用虚拟方法,因为指向该方法的指针为NULL(如VS所示),因此发生内存访问冲突异常。怎么会这样?

应用程序相当大而且很复杂,所以我真的不知道是什么低级步骤导致了这种情况。发布原始代码没有用。

UPD:好的,我看到我对问题的描述是相当不确定的,所以示意性代码看起来像

void MyClass::FirstMethod() const { /* Do stuff */ }
void MyClass::SecondMethod() const
{
    // This is where exception occurs, 
    // description of this method during runtime in VS looks like 0x000000
    FirstMethod(); 
}

不涉及构造函数或析构函数。

4

7 回答 7

6

堆损坏是一个可能的候选者。对象中的 v-table 指针是易受攻击的,它通常是对象中的第一个字段。碰巧与该对象相邻的某种其他对象的缓冲区溢出将擦除 v-table 指针。对虚拟方法的调用,通常是很久以后的,会失败。

另一个经典案例是“this”指针错误,通常为 NULL 或低值。当您调用该方法的对象引用不正确时,就会发生这种情况。该方法将照常运行,但一旦尝试访问类成员就会崩溃。同样,堆损坏或使用已删除的指针会导致此问题。祝你调试好运;这绝非易事。

于 2010-02-11T20:19:22.500 回答
2

可能您正在从本身没有该功能的基类的构造函数中调用该函数(直接或间接)。

可能某处存在损坏的强制转换(例如reinterpret_cast涉及多重继承时的指针),并且您正在查看错误类的 vtable。

可能(但不太可能)您以某种方式破坏了 vtable。

指向函数 null 的指针是仅针对该对象,还是针对所有其他相同类型的对象?如果是前者,那么 vtable 指针就坏了,你找错地方了。如果是后者,则 vtable 本身已损坏。

于 2010-02-11T19:58:15.280 回答
1

在 SecondMethod 的处理过程中是否有可能“this”指针被删除?

另一种可能性是 SecondMethod 实际上是在前面使用无效指针调用的,并且它恰好工作(通过未定义的行为)直到嵌套函数调用然后失败。如果您能够添加打印代码,请检查“this”和/或其他正在使用的指针在执行这些方法期间的各个点是否类似于 0xcdcdcdcd 或 0xfdfdfdfd。这些值(我相信)被 VS 用于内存分配/释放,这可能是它在调试模式下编译时工作的原因。

于 2010-02-11T21:11:37.017 回答
1

这可能发生的一种情况是,如果您尝试在析构函数或构造函数中调用纯虚方法。此时,该方法的虚拟表指针可能未初始化,从而导致崩溃。

于 2010-02-11T19:56:40.460 回答
0

如果您的 this 指针为 NULL,则不太可能发生损坏。除非你将你不应该有的内存归零。

您没有说您是在调试 Debug(未优化)还是 Release(优化)构建。通常,如果不需要,在 Release 构建优化器将删除此指针。因此,如果您正在调试优化构建,则将此指针视为 0 并没有任何意义。您必须依靠反汇编来告诉您发生了什么。如果无法在调试版本中重现问题,请尝试在发布版本中关闭优化。调试优化构建时,您正在调试程序集而不是 C++。

如果您已经在调试未优化的构建,请确保在花费太多时间调试损坏的图像之前进行干净的重建。调试版本通常以增量方式链接,并且已知增量链接器会产生此类问题。如果您正在使用 clean build 运行 Debug build 并且仍然无法找出问题所在,请发布堆栈转储和更多代码。我相信我们可以帮助您解决问题。

于 2010-02-12T05:07:34.227 回答
0

如果仅在 Studio 无法显示方法地址时发生内存访问冲突,则可能是由于缺少调试信息造成的。您可能正在调试使用发布(非调试)编译器/链接器标志编译的代码。

尝试在项目的 C++ 属性中启用一些调试信息,重新构建并重新启动调试器。如果它有帮助,您将看到所有正常的可追踪事物,如堆栈、变量等。

于 2010-02-12T01:04:14.233 回答
0

您最有可能看到的是实际问题的副作用。很可能是堆或内存损坏,或者引用了以前释放的对象或空指针。

如果您可以始终让它在同一个地方崩溃并且可以确定从哪里加载空指针,那么我建议使用调试器并在该内存位置的“写入”上放置一个断点,一旦触发断点,那么很可能您正在查看实际导致损坏的代码。

于 2010-02-12T00:57:34.697 回答