3

我正在处理来自 3rd-Pary 库的一个庞大的类,这里是相关内容的摘录:

class SomeClass {
    // ...
public:
    // ...
    virtual int SetTableSize(unsigned int uiTableID, int iSize);
    // ...
protected:
    // ...
    virtual int Set_0xB0_0x23_IsoTableData(unsigned char* ucData, int iLen);
    // ...
};

我的应用程序因内存访问冲突而中断。调用堆栈中最上面的一项是 的实现中的代码行Set_0xB0_0x23_IsoTableData,第二项是这样的代码行:

someClassInstance.SetTableSize(2, 400);

在调试视图中,ucData有 value 0x00000002,所以它看起来不像调用 的实现SetTableSize,这应该根据代码发生,而是Set_0xB0_0x23_IsoTableData使用指定的参数调用 - 这显然会导致错误,因为指针无效。

我已经花了很多时间弄清楚这里发生了什么。我在 Linux 上使用 GCC 在不同的应用程序中编译相同的代码,它在那里工作。这是 Visual Studio 编译器错误吗?编译此代码时,我没有收到任何警告。

不可能构建一个最小的工作示例来重现该错误 - 至少在我弄清楚发生这种情况的原因之前是不可能的。标SomeClass头中确实有很多#ifdefs,所以我首先想到的是编译包含的模块时的预处理器定义与SomeClass编译调用代码时的不同。但是,我仔细检查了,定义是一样的。

所以我想问的基本上是:

  • 在什么情况下调用一个虚方法可以调用另一个虚方法的实现?(这与继承无关——这两个方法在同一个类中定义,甚至不共享它们的签名并且具有不同的可见性)
  • 如何调试这样的错误?是否可以在 Visual Studio 中查看类实例的调度向量?
4

1 回答 1

0

我对这类问题的标准答案是:全部重建。在某些情况下,它就像那样简单/愚蠢(至少对于 Visual Studio)。

如果错误仍然存​​在,那么我要做的是调试:尽可能运行代码“它现在不可能发生”。然后一步步调试,逐行调试,仔细观察调用堆栈。

不,这不好玩。

于 2014-03-12T10:06:09.067 回答