正如您在下面的代码中看到的那样,我有一个抽象基类“HostWindow”,以及源自它的类“Chrome”。所有功能都在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实例 - 它无法正确实例化。现在,Chrome实例在另一个类的构造函数中实例化。我会进一步调查...
更新2: 好吧,检查有问题的实例的vtable表明它是空的;从GDB:
p *(void **)chrome
$52 = (void *) 0x0
正常情况下有一个正确的虚函数表。所以,我必须弄清楚为什么vtable是零 - 我想知道这是怎么发生的?也许是因为它在其他一些类中被实例化了构造函数?
更新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;
}
现在这一页::铬()情况下是正确的,与适当的vtable - 相当奇怪!
更新4: 最后更新,我保证:)。好吧,我已经准确地指出了它。如果在页面构造函数的主体中实例化它,你可以用vtable获得正确的实例。如果你在页面构造函数的头部实例化它,它没有一个vtable。在构造函数头部可以进行的变量设置类型是否有任何限制?我想这是另一个Stackoverflow问题。
非常感谢你们的帮助。
使用复制和粘贴来发布REAL代码。 – 2010-01-12 13:38:11
这是真实的代码。我无法使它更简洁,因为它在WebKit中是正确的。 – 2010-01-12 15:10:43
在通话'WebCore :: Chrome * chrome = new Chrome()'之后,'chrome'的值是什么?';'如果为NULL,是否抛出异常? – 2010-01-12 15:18:54