2010-01-12 96 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需要的東西。

我改變了這一點,導出每一個符號 - 它不知何故導致這個錯誤。