Question

Comme vous pouvez le voir dans le code ci-dessous, j'ai une classe abstraite de base « HostWindow », et la classe qui en dérive « Chrome ». Toutes les fonctions sont mises en œuvre dans Chrome. La question est, je ne peux pas appeler des fonctions dans Chrome si elles sont 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:

  

Programme signal reçu EXC_BAD_ACCESS, n'a pas pu accéder à la mémoire.   Motif: KERN_PROTECTION_FAILURE à l'adresse: 0x00000008

Une idée de ce qui se passe?

Mise à jour: Comme beaucoup d'entre vous ont souligné - ce code fonctionne réellement. Malheureusement, je ne peux pas donner un exemple plus complet, puisque le code est plus profond WebCore (WebKit). Cependant, j'ai rétréci le problème vers le bas. Si je crée une instance Chrome manuellement, appelant des fonctions virtuelles fonctionnent. La question est donc avec cette instance de chrome particulier - il ne peut pas instancié correctement. Maintenant, l'instance Chrome est instancié dans un constructeur d'une autre classe. Je ... explorera d'autres

Mise à jour 2: Ok, l'examen de la vtable sur l'instance incriminée montre qu'il est nul; de GDB:

p *(void **)chrome
$52 = (void *) 0x0

Une instance normale a une vtable correcte. Donc, je dois comprendre pourquoi le vtable est nul - Je me demande comment cela pourrait se produire? Peut-être parce qu'il est instancié dans certaines autres classes Constructor?

Mise à jour 3: On dirait que je ne me trompe pas sur la question étant, il est instanciation dans une autre classe constructeur.

Alors, 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. Je l'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 approprié - plutôt étrange

Mise à jour 4: Dernière mise à jour, je vous le promets :). Ok, donc je l'ai mis le doigt vers le bas exactement. Vous obtenez l'instance correcte, avec le vtable, si vous instancier dans le corps de la page constructeur. Si vous instanciez dans la tête de la page constructeur, il ne dispose pas d'un vtable. Y at-il de limiter les types de définition de la variable que vous pouvez faire dans la tête d'un constructeur? Je suppose que c'est une autre question Stackoverflow.

Merci les gars pour avoir été si utile.

Était-ce utile?

La solution

Oui, le pointeur 'this' est égal à zéro. Ajouter 8 pour obtenir un décalage, et il est de votre faute. Vous ne semble pas avoir un objet réel du tout.

Puisque vous ne l'avez pas affiché assez de code pour venir vraiment aux prises, je devine. Soit l'ensemble de ce pointeur est 0 ou le pointeur de la table de fonction virtuelle est 0, peut-être parce que l'objet a été supprimé après sa création et avant d'essayer de l'appeler.

Le meilleur conseil que je peux vous donner est de créer un tube à essai beaucoup plus petit. Soit vous trouverez votre problème ou vous finirez par un exemple buchbar.

Le vtbl est pas en place dans une instance jusqu'à la fin du processus de construction. En fait, la spécification nécessite une modification progressive du vtbl pour correspondre à l'état de construction de la hiérarchie des classes.

Autres conseils

Pouvez-vous envoyer le code complet?

Après une légère modification dans votre code (ce qui est disponible), il fonctionne:

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

Je ne suis pas au courant de la base de code que vous avez, mais vous ne devriez pas écrire:

// note the 'WebCore::Chrome()'
WebCore::Chrome *chrome = new WebCore::Chrome();
chrome->repaint(IntRect(), true); // 'chrome' should be a valid pointer now

au lieu de:

WebCore::Chrome *chrome = new Chrome();
chrome->repaint(IntRect(), true); // Null pointer error

ssume votre incopiable sont les suivantes (au moins pour le mien a fait)

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

après l'insertion publique modificateur à la fonction de la classe chrome et une mise en œuvre factice pour eux, tout cela a fonctionné sans problème posé.

  
    
      

il n'y a pas de problème avec le code affiché, il est peut-être que vous faites des choses mauvaises et ne pas poster ici ceux qui font partie.

    
  

enfin, DO vérification de l'échec de l'allocation. (Oui, "nouveau" sont sur l'allocation tas)

Je trouve que cela a été causé en permettant à tous les symboles à exporter.

En général, WebCore a un sous-ensemble de symboles exportés -. Essentiellement sur des choses que les besoins WebKit

J'ai changé que pour exporter tous les symboles - et il a causé une certaine façon cette erreur

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top