2010-01-12 192 views
1

正如您在下面的代码中看到的那样,我有一个抽象基类“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问题。

非常感谢你们的帮助。

+2

使用复制和粘贴来发布REAL代码。 – 2010-01-12 13:38:11

+0

这是真实的代码。我无法使它更简洁,因为它在WebKit中是正确的。 – 2010-01-12 15:10:43

+0

在通话'WebCore :: Chrome * chrome = new Chrome()'之后,'chrome'的值是什么?';'如果为NULL,是否抛出异常? – 2010-01-12 15:18:54

回答

2

是的,'this'指针是零。加8来获得偏移量,这是你的错。你显然没有任何实际的物体。

既然你还没有发布足够的代码来真正来握手,我猜。无论是整个这个指针是0还是虚拟函数表指针都是0,可能是因为该对象在创建之后以及在尝试调用它之前已被删除。

我可以给你的最好建议是创建一个更小的试管。要么你会发现你的问题,要么你最终会得到一个可信的例子。

直到施工过程结束时,vtbl在一个实例中不存在。实际上,规范要求逐步修改vtbl以匹配类层次结构的构建状态。

+0

您能详细说明吗?我对C++相当陌生。 我确实有一个实例Chrome,我可以调用一些函数 - 比如focus(),但不能在ABC中定义像repaint()。 – 2010-01-12 13:50:03

+0

'Chrome'不是实例,它是类。 'chrome'是实例。 – 2010-01-12 15:17:31

+0

vtable是零 - 请参阅更新。我不知道它会如何发生。 – 2010-01-13 00:28:51

0

你能发布完整的代码吗?

在你的代码稍加修改(无论是可用的)后,它的工作原理:

#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; 
} 
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 
+0

是的,这是一个例子中的拼写错误。 – 2010-01-12 15:09:25

+1

@Alex:这就是为什么你应该总是剪切/粘贴代码。 __NEVER__重新键入,因为它只是增加了错误,并导致大量繁忙的空工作帮助你的人。 – 2010-01-12 16:39:52

0

ssume您不可复制的表现如下(至少对于我的一样)

class NonCopyable 
{ 
protected: 
    NonCopyable() {} 
    ~NonCopyable() {} 
private: 
    NonCopyable(const NonCopyable&); 
    const NonCopyable& operator=(const NonCopyable&); 
}; 

插入公共改性剂类Chrome的功能,并为他们一些虚拟实施后,整个事情的工作没有指出问题。

没有问题的代码发布,这可能是你正在做的事情错了,这里不是张贴那些部分。

最后,不要检查分配失败。 (是的,“新”分配在堆上)

+0

您是否阅读过更新? – 2010-01-13 12:07:05

+0

不幸的是,我做了... 什么是类页? u增加了一些代码片段,没有其他人理解的细节 – YeenFei 2010-01-15 01:24:09

0

我发现这是由于允许导出所有符号引起的。

通常,WebCore只有一部分导出的符号 - 基本上是WebKit需要的东西。

我改变了这一点,导出每一个符号 - 它不知何故导致这个错误。