Domanda

Come si può vedere nel codice qui sotto, ho un "HostWindow" classe di base astratta, e la classe che ne deriva "Chrome". Tutte le funzioni sono implementate in Chrome. Il problema è, non posso chiamare funzioni in Chrome se sono virtuali.

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

Quindi, consente di dire che abbiamo un caso di Chrome, e che noi chiamiamo alcune funzioni:

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

L'errore di puntatore nullo ricevo ogni volta che io chiamo le funzioni virtuali è:

  

Programma ricevuto EXC_BAD_ACCESS segnale, Impossibile accedere alla memoria.   Motivo: KERN_PROTECTION_FAILURE all'indirizzo: 0x00000008

Qualche idea di cosa sta succedendo?

Aggiornamento: Come molti di voi hanno sottolineato - questo codice viene eseguito in realtà. Purtroppo non posso fornire un esempio più completo, dal momento che il codice è profondo WebCore (WebKit). Tuttavia, ho ristretto il problema verso il basso. Se creo un'istanza Chrome manualmente, chiamando funzioni virtuali funzionano. Quindi il problema è con questo caso particolare cromo - non può un'istanza correttamente. Ora, l'istanza di Chrome viene creata un'istanza in un costruttore di un'altra classe. Io indagare ulteriormente ...

Aggiornamento 2: Ok, esaminando vtable nell'istanza offendere indica che è nullo; da GDB:

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

Un esempio normale ha una corretta vtable. Così, ho avuto modo di capire perché il vtable è pari a zero - mi chiedo come sia potuto accadere? Forse perché è in fase di un'istanza in alcune altre classi Constructor?

Aggiornamento 3: Sembra come se fossi una corretta informazione circa la questione di essere è esemplificazione all'interno di un altro costruttore della classe.

Quindi, prima l'istanza si presentava così:

Page::Page(ChromeClient* chromeClient, ...)
    : m_chrome(new Chrome(this, chromeClient))

E m_chrome è un'istanza valida, con un vtable nullo. Ho cambiato l'istanza in modo che succede quando la prima volta che è necessaria la variabile (si tratta di risparmio ChromeClient per dopo):

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

Ora l'istanza Pagina :: cromo () è quella corretta, con il corretto vtable - piuttosto strano

!

Aggiornamento 4: Ultimo aggiornamento, lo prometto :). Ok, così ho individuato il basso esattamente. Si ottiene l'istanza corretta, con il vtable, se si crea un'istanza di esso nel corpo Pagina del costruttore. Se si crea un'istanza in testa Pagina del costruttore, che non dispone di un vtable. Ci sono limitazioni nel tipo di variabile impostazione che si può fare nella testa di un costruttore? Direi che è un'altra questione StackOverflow.

Grazie ragazzi per essere così utile.

È stato utile?

Soluzione

Sì, il puntatore 'this' è pari a zero. Aggiungere 8 per ottenere un offset, e c'è colpa tua. È a quanto pare non hanno alcun oggetto reale a tutti.

Dal momento che non hai postato abbastanza codice di venire davvero i conti, sto cercando di indovinare. O l'intera questo puntatore è 0, o il puntatore tabella di funzione virtuale è 0, forse perché l'oggetto è stato eliminato dopo che è stato creato e prima di provare a chiamarla.

Il miglior consiglio che posso darvi è quello di creare una provetta molto più piccolo. O si trova il vostro problema o si finirà con un esempio postable.

Il vtbl non è a posto in un'istanza fino alla fine del processo di costruzione. Infatti, le specifiche richiede progressiva modifica della vtbl per corrispondere allo stato di costruzione della gerarchia delle classi.

Altri suggerimenti

Puoi pubblicare il codice completo?

Dopo la leggera modifica nel codice (tutto ciò che è disponibile), funziona:

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

Non ho dimestichezza con il codice di base che hai, ma non dovresti scrivere il seguente:

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

invece che:

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

ssume tuo non copiabile sono i seguenti (almeno per il mio ha fatto)

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

dopo l'inserimento di pubblici modificatore alla funzione di classe di cromo e qualche implementazione manichino per loro, il tutto ha funzionato senza problemi dichiarato.

  
    
      

non ci sono problemi con il codice scritto, potrebbe essere che si sta facendo le cose sbagliate e non inviare quelle parte qui.

    
  

infine, DO controllando errore di allocazione. (Sì, "nuovo" sono di allocazione sul mucchio)

ho scoperto che questo è stato causato da permettere tutti i simboli da esportare.

Di solito, WebCore ha solo un sottoinsieme di simboli esportati -. Essenzialmente sulle cose che le esigenze WebKit

ho cambiato che per esportare ogni simbolo - e in qualche modo ha causato questo errore

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top