【问题标题】:C++ rare runtime errorC++ 罕见的运行时错误
【发布时间】:2011-12-02 09:41:15
【问题描述】:

我有一个类 B,它通过一些虚函数继承了类 A。 B 类还有一个似乎没有地址的虚函数(foo)。当我使用调试器时,它指出 foo 具有0x00000000 地址,当我尝试介入时,它将在0x00000005 出现访问冲突而失败。如果我使该功能不是虚拟的,则调试器会介入并可以正常工作,直到我达到std::vector。在那里,当我调用push_back 时,它会在地址0x000000005 处写一些东西,同时在地址0xabababab 处写一些东西时会失败,并且调用堆栈指向插入函数中的互斥锁。

注意:我没有使用任何其他线程,每次编译时增量链接器都会崩溃。只有完整的链接器才能成功创建 exe。编译器来自 Visual Studio 2008 pro,当剥离未使用的源文件和源代码时开始出现此问题。

很遗憾,我无法恢复到以前的状态,以便发现造成这种情况的变化。

如何在不恢复整个项目的情况下检测问题的根源?也有人遇到过这种错误,可能是同一个原因。

【问题讨论】:

  • 给我们一些代码。
  • 最可能的原因是您通过空指针调用成员函数。
  • 我正在使用调试器,但它没有给我任何相关信息。指针不为空,不幸的是我不能给你任何源代码。
  • 您的代码中的其他地方可能出现问题,并覆盖了您的一个对象中的 vtable 指针。如果在特定对象中调用函数时可以可靠地重现它,请在创建该对象后立即设置断点,然后为该对象上的 vtable 指针设置观察点(您可能必须检查内存位置 - 不要'不记得 Visual C++ 调试器是否将 vtable 指针作为成员公开),并且一旦内存覆盖代码运行,您应该触发该观察点。
  • ...如果这不起作用,我捕获内存损坏错误的标准解决方案是在 Linux and use valgrind 下编译它以在错误发生时捕获它们。当然,这确实需要您首先编写代码,以便它可以跨平台编译。

标签: c++ linker runtime linker-errors


【解决方案1】:

您猜测虚拟表已损坏,但这不太可能,因为虚拟表通常存储在只读内存中。

我可以想到这种行为的两个原因:

  • 您正在使用的对象已被删除。如果对象曾经所在的内存可能会偶然工作,但如果它被覆盖,则会惨遭失败。
  • 您使用的对象不是动态类型 B。可能是 A 类型,也可能是不相关的类型。

我已经成功地跟踪到了这种 printf 调试的问题:在 B 的构造函数、析构函数、虚函数和失败函数中添加几行 printf("XXX %p", this);,然后你就能推断出发生了什么。

是的,我知道,printf 调试并不酷...

【讨论】:

    【解决方案2】:

    您正在对空指针调用虚函数。编译器添加的代码将使用对象中的隐藏指针来定位最终覆盖器,并且该操作失败。当您将函数更改为非虚拟函数时,调用是静态调度的,但同样,由于this 指针为空,对成员的访问也会失败。

    您应该检查您在代码中调用该方法的对象的有效性。

    【讨论】:

    • @Raxvan:尝试在非虚拟版本中打印(void*)this,看看打印出来的内容。
    • 发现错误,B类没有创建。指针应该保留 B 类,但它包含其他类。
    • 在 google 中快速查看后,位模式0xabababab 在 windows CRT 中用于标记已分配但未初始化或已释放的内存,因此它可能不指向 any 对象
    • 你是对的,指针指向 A 类,而 B 类的内存占用更大。失败点在于可能指向未初始化空间的额外字节
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    相关资源
    最近更新 更多