继承的类“无效指针错误”调用虚函数时
-
20-09-2019 - |
题
可以在下面的代码看,我有一个抽象基类“HostWindow”,和从它“铬”派生类。所有的功能都在Chrome中实现的。问题是,如果他们是虚拟的,我不能调用函数在Chrome。
class HostWindow : public Noncopyable {
public:
virtual ~HostWindow() { }
// Pure virtual functions:
virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false) = 0;
virtual void scrollbarsModeDidChange() const = 0;
}
class Chrome : public HostWindow {
// HostWindow functions:
virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false);
virtual void scrollbarsModeDidChange() const;
void focus() const;
}
因此,可以说,我们有镀铬的一个实例,我们所说的几个功能:
WebCore::Chrome *chrome = new Chrome();
chrome->repaint(IntRect(), true); // Null pointer error
chrome->focus(); // returns void (works)
在空指针错误我得到每当我调用虚函数是:
方案接收信号EXC_BAD_ACCESS,无法访问存储器。 原因是:在KERN_PROTECTION_FAILURE地址:0x00000008
任何想法是怎么回事?
<强>更新强> 正如你们许多人指出的 - 这个代码实际运行。不幸的是,我不能提供一个更加充满例子,因为代码是内部的WebCore(WebKit的)深。不过,我已经收窄的问题。如果我手动创建一个Chrome的实例,调用虚函数工作。所以,问题是与这个特殊的镀铬实例 - 它不能正确实例化。现在,Chrome浏览器实例在另一个类的构造函数实例。我会进一步调查......
<强>更新2:强> 好了,检查有冲突的情况下的虚函数表显示,这是空;从GDB:
p *(void **)chrome
$52 = (void *) 0x0
一个正常的实例有一个正确的虚表。所以,我得工作了,为什么虚函数表是零 - 我不知道怎么会发生呢?也许是因为它被实例化在一些其他类的构造函数?
<强>更新3:强> 貌似我对这个问题是它的内部另一个类的构造函数实例化正确的。
所以,在实例化是这样的:
Page::Page(ChromeClient* chromeClient, ...)
: m_chrome(new Chrome(this, chromeClient))
和m_chrome是无效的情况下,用零虚表。 我已经改变的实例化,以便它发生时第一次需要的变量(在此包括保存ChromeClient购买):
Page::Page(ChromeClient* chromeClient, ...)
: m_chrome(0)
, m_chrome_client(chromeClient)
Chrome* Page::chrome() const {
if(!m_chrome) {
m_chrome = new Chrome(this, m_chrome_client);
}
return m_chrome;
}
现在的页::铬()情况下是正确的,用适当的虚函数表 - 而奇
!<强>更新4:强> 最近更新的,我保证:)。好了,我已经确切地精确定位下来。你得到正确的实例,用虚函数表,如果你在页面构造的身体实例化。如果您在页面构造的头部实例,它没有一个虚函数表。是否有在类型变量的设置,您可以在构造函数中的头做任何限制吗?我想这是另一个问题#1
由于球员被如此有益的。
解决方案
是,则“这个”指针是零。加8获得的偏移,并且有是你的错。你显然不具有任何实际的对象都没有。
由于您没有足够的发布代码,真正交手,我猜。无论是整个这个指针为0,或虚函数表指针为0,也许是因为它被创建后该对象已被删除,您尝试调用它。
我可以给你最好的建议是建立一个更小的试管中。要么你会发现你的问题,或者你会最终有一个可发布的例子。
在VTBL不到位在一个实例直到施工过程的结束。事实上,该规范要求VTBL的渐进修改以匹配结构的类层次结构的状态。
其他提示
你能发布完整的代码?
在代码轻微的修改(无论是可用的),它的工作原理后:
#include <iostream>
class HostWindow {
public:
virtual ~HostWindow() { }
// Pure virtual functions:
virtual void repaint(const int , bool contentChanged, bool immediate = false, bool repaintContentOnly = false) = 0;
virtual void scrollbarsModeDidChange() const = 0;
};
class Chrome : public HostWindow {
public:
// HostWindow functions:
virtual void repaint(const int , bool contentChanged, bool immediate = false, bool repaintContentOnly = false)
{
std::cout << "In repaint." << std::endl;
}
virtual void scrollbarsModeDidChange() const { }
void focus() const
{
std::cout << "In focus." << std::endl;
}
};
int main()
{
Chrome *chrome = new Chrome();
chrome->repaint(1, true); // Null pointer error
chrome->focus();
delete chrome;
return 0;
}
我不熟悉你的代码基础,但你不应该写:
// note the 'WebCore::Chrome()'
WebCore::Chrome *chrome = new WebCore::Chrome();
chrome->repaint(IntRect(), true); // 'chrome' should be a valid pointer now
,而不是:
WebCore::Chrome *chrome = new Chrome();
chrome->repaint(IntRect(), true); // Null pointer error
ssume您的不可复制表现如下(至少对于矿一样)
class NonCopyable
{
protected:
NonCopyable() {}
~NonCopyable() {}
private:
NonCopyable( const NonCopyable& );
const NonCopyable& operator=( const NonCopyable& );
};
在插入后的公共的修改,以一流的Chrome的功能,并为他们的一些虚拟实现,整个事情的工作没有规定的问题。
有与发布的代码没有问题,它可能是你正在做的事情错了,这里没有张贴这些部分。
最后,DO检查分配失败。 (是的, “新” 是在堆分配)
我发现,这正在通过允许导出的全部符号引起的。
通常,WebCore的只有导出的符号的一个子集 - 基本上对事物WebKit所需要
我改变了每个码元导出 - 和它在某种程度上导致该错误
。