正如您在下面的代碼中看到的那樣,我有一個抽象基類「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