Comme vous pouvez le voir dans le code ci-dessous, j'ai une classe de base abstraite "HostWindow" et une classe qui en dérive "Chrome". Toutes les fonctions sont implémentées dans Chrome. Le problème est que je ne peux pas appeler des fonctions dans Chrome si elles sont virtuelles.Classe héritée "erreur de pointeur non valide" lors de l'appel de fonctions virtuelles
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;
}
Disons donc que nous avons une instance de Chrome, et nous appelons quelques fonctions:
WebCore::Chrome *chrome = new Chrome();
chrome->repaint(IntRect(), true); // Null pointer error
chrome->focus(); // returns void (works)
L'erreur de pointeur NULL je reçois chaque fois que j'appelle des fonctions virtuelles est:
Le programme a reçu le signal EXC_BAD_ACCESS, Impossible d'accéder à la mémoire. Raison: KERN_PROTECTION_FAILURE à l'adresse: 0x00000008
Toute idée de ce qui se passe?
Mise à jour: Comme beaucoup d'entre vous l'ont fait remarquer - ce code fonctionne réellement. Malheureusement, je ne peux pas donner un exemple plus complet, car le code est profond dans WebCore (WebKit). Cependant, j'ai réduit le problème. Si je crée une instance Chrome manuellement, l'appel des fonctions virtuelles fonctionne. Donc, le problème est avec cette instance de chrome particulière - il ne peut pas instancié correctement. Maintenant, l'instance de Chrome est instanciée dans un constructeur d'une autre classe. Je vais étudier plus en détail ...
Mise à jour 2: Ok, l'examen de la vtable sur l'instance incriminée montre que c'est null; à partir de GDB:
p *(void **)chrome
$52 = (void *) 0x0
Une instance normale a une vtable correcte. Donc, je dois déterminer pourquoi le vtable est nul - je me demande comment cela pourrait arriver? Peut-être parce qu'il est instancié dans d'autres classes constructeur?
Mise à jour 3: On dirait que j'ai raison à propos de l'instanciation dans un autre constructeur de classe.
Ainsi, avant l'instanciation ressemblait à ceci:
Page::Page(ChromeClient* chromeClient, ...)
: m_chrome(new Chrome(this, chromeClient))
Et m_chrome est une instance non valide, avec un vtable nul. J'ai changé l'instanciation de sorte qu'il se produit lorsque la première fois que la variable est nécessaire (ce qui implique l'enregistrement ChromeClient pour plus tard):
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;
}
Maintenant, la page :: instance chrome() est correcte, avec le vtable propre - plutôt étrange!
Mise à jour 4: Dernière mise à jour, je promets :). Ok, donc je l'ai localisé exactement. Vous obtenez l'instance correcte, avec vtable, si vous l'instanciez dans le corps du constructeur de Page. Si vous l'instanciez dans la tête du constructeur de Page, il n'a pas de vtable. Y a-t-il une limitation dans les types de paramètres de variables que vous pouvez faire dans la tête d'un constructeur? Je suppose que c'est une autre question Stackoverflow.
Merci les gars d'être si utile.
Veuillez publier le code REAL en utilisant copier et coller. –
Ceci est le code réel. Je ne peux pas le rendre plus succinct car c'est juste au milieu de WebKit. –
Quelle est la valeur de 'chrome' immédiatement après l'appel 'WebCore :: Chrome * chrome = new Chrome();' Si NULL, une exception est-elle levée? –