0

我目前面临 VS08 的问题。我得到了以下(简化的)类结构:

class CBase
{
    public:
    virtual void Func() = 0;
};

class CDerived : public CBase
{
public:
    void Func();
};

此代码在发布模式下运行良好,但是当我尝试运行调试构建时,它会立即在new CDerived.

进一步的分析使我能够找到崩溃的位置。它在 CBase::CBase (编译器生成的构造函数)处崩溃。更准确地说,它在04AE46C6 mov dword ptr [eax],offset CBase::vftable' (505C2CCh) ` 处崩溃。

有什么线索吗?发布模式很好,但我无法正确调试它。

4

2 回答 2

1

释放模式很好

不,它似乎很好。我的猜测是在调试内存以某种方式被覆盖。由于无法仅从您发布的代码中判断,这就是您可以执行的操作。

我假设您在某处创建对象:

CBase* p = new CDerived;

或类似的。在调试模式下,在' 位置设置内存断点。p您可以将其设置为监视 4 个字节。Visual C++(像大多数编译器一样)会将 vfptr 作为类中的第一件事,因此此断点将跟踪该位置是否被覆盖。如果断点在你调用它崩溃的函数之前被命中,那就是你的问题(调用堆栈会告诉你为什么它被覆盖)。

这可能有很多原因 - 您可能会超出一些内存并覆盖对象(正如 Erik 建议的那样) - 发布版本可能会直接解决调用以防止动态调度的开销,这可以解释为什么它没有崩溃。

也可能是您调用delete了对象,而调试版本实际上将内存清零,而发布版本则没有。没有办法仅凭此说。

于 2013-02-13T21:22:50.657 回答
1

在这里发布一些死灵,但我想为未来的访客提出一点......

正如其他人所说,这可能是内存损坏或免费+重用问题。您不应该仅仅因为您能够通过更改编译器设置或重新排列代码来消除崩溃,就认为这是一个编译器错误。如果这是一个损坏错误,您可能所做的是将损坏移到不会导致程序崩溃的某些内存中——无论如何,在您当前的构建中,在您当前的操作系统和架构上。

仅仅达到不崩溃的地步可能已经足以满足您的即时需求,但与此同时,您并没有学会避免任何导致您首先编写错误的做法。工程师之间有一句由来已久的谚语,可能还有相当多的其他学科:

“自己消失的东西,可以自己回来。”

它可能是任何形式的工程中最真实和最重要的谚语之一。如果你没有亲眼看到虫子死去,你应该总是为此感到焦虑。它应该深深地困扰你。该错误可能仍然存在,等待您的下一个里程碑之夜再次抬头。

Luchian Grigore 就找到内存断点的真正问题给出了很好的建议。

于 2014-02-14T02:28:48.500 回答