【问题标题】:VSC++, virtual method at bad address, curious bugVSC++,错误地址的虚拟方法,奇怪的错误
【发布时间】:2011-03-03 13:29:38
【问题描述】:

这个人:

virtual phTreeClass* GetTreeClass() const { return (phTreeClass*)m_entity_class; }

调用时,程序因访问冲突而崩溃,即使在完全重新编译后也是如此。所有成员函数和虚拟成员函数都有正确的内存地址(我将鼠标悬停在调试模式下的方法上),但这个函数的内存地址错误:0xfffffffc。

一切看起来都还不错:'this' 指针,在调用此函数之前一切正常。这个功能也比较老了,好久没改了。这个问题只是在一些工作后突然出现,我把它全部注释掉,看看是什么做的,没有任何成功。

所以我去掉了虚拟,编译好了,效果很好。我添加了虚拟的,编译的,它仍然可以正常工作!我基本上什么都没做,记得之前我确实做了完整的重新编译,但当时仍然有错误。

我无法重现该问题。但现在它又回来了。我没有改变任何东西。删除虚拟可以解决问题。

【问题讨论】:

  • 作为一个简短的评论,在处理 C++ 类层次结构时,您应该真正避免使用 C 风格的强制转换,尤其是在处理多态类时。出错的机会太多了。
  • 我怀疑删除virtual“固定”任何东西。未定义的行为是不可预测的,当你改变一些无辜的东西时,它甚至可能会起作用。您必须做必要的工作才能重现此内容。您很可能会以这种方式找到错误。如果没有,您可以在这里展示一个很好的复制案例并征求其他意见。
  • 我们真的需要看到比这更多的代码才能有任何用处。我的意思是,m_entity_class 来自哪里?它是什么类型的?哪些函数会影响它,它们何时被调用,有哪些用例?
  • 是否涉及多重继承?

标签: c++ visual-studio-2008 methods virtual memory-address


【解决方案1】:

除非您非常确定自己在做什么,否则永远不要对多态类型使用 C 风格的强制转换。压倒性的可能性是您将其转换为不是的类型。如果您的指针没有隐式转换(因为它们转换为安全的基类),那么您做错了。

【讨论】:

  • 即使那样,也不要使用它们,其中一种 C++ 强制转换将起作用,使用它会显示您的意思
  • 谢谢,我仍在努力获得 C++ 风格的演员表,现在在这些方法中进行了更改。在这种情况下,我只使用 base to child cast,因为我不想浪费内存为每个子类保存指针。
  • 您的错误可能存在,因为它不是子类。如果您有孩子*,请将其存储为孩子*。如果您有一个基地*,请不要将其上载给孩子*。
【解决方案2】:

编译器和链接器是人类编写的软件,与其他任何软件一样,因此天生就不可能没有错误。..

我们偶尔也会遇到此类莫名其妙的问题并进行修复。这里有一个神话,一旦修复了构建,就删除 ncb 文件..

【讨论】:

  • 没错,但归咎于编译器和/或链接器几乎总是被证明是错误的。 :)
  • 实际上重建更有可能导致以前未重建的文件被重新编译,从而解决了问题。编译器总是表现不正确的可能性不大,但有时工作有时失败的编译器则更不可能。
  • 你可能是对的。我现在只是感到沮丧,因为我目前正在遇到积极的链接器问题(incredibuild/local 构建兼容性,不要问)
【解决方案3】:

鉴于重新编译最初解决了问题,请尝试先进行完全清理并重新构建。

如果失败了,那么即使您的 this 指针对您来说似乎是正确的,它看起来也极有可能被删除/解构并指向垃圾内存,而垃圾内存恰好看起来像之前存在的真实对象.如果您使用 gdb 进行调试,则对象指针处的第一个单词将是 vtable。如果你在那个位置做一个x/16xw <addr>(例如)内存转储,gdb 会告诉你什么样的对象的 vtable 驻留在那里。如果它是最父类型,那么该对象肯定已经消失了。

如果this指针每次都相同,则可以在类析构函数中放置断点,条件为this == known_addr

【讨论】:

  • 谢谢,尤其是最后的提示。我关闭了内存释放,它仍在发生..
猜你喜欢
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 2011-07-10
  • 2014-04-14
  • 2010-11-17
  • 1970-01-01
相关资源
最近更新 更多