Как вы можете видеть в приведенном ниже коде, у меня есть абстрактный базовый класс «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;
}
Так позволяет сказать, что у нас есть экземпляр Chrome, и мы называем несколько функций:
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. Итак, мне нужно разобраться, почему vtable - ноль - интересно, как это могло случиться? Может быть, потому, что он создается в некоторых других классах Constructor?
Обновление 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.
Спасибо, ребята, за то, что они так полезны.
PLease опубликуйте код REAL с помощью копирования и вставки. –
Это настоящий код. Я не могу сделать это более кратким, поскольку это правильно в середине WebKit. –
Какова ценность «chrome» сразу после вызова «WebCore :: Chrome» chrome = new Chrome(); Если NULL, исключение выбрасывается? –