Pregunta

Como se puede ver en el código siguiente, tengo una "HostWindow" clase base abstracta, y la clase que se deriva de ella "Chrome". Todas las funciones se implementan en Chrome. La cuestión es, no puedo llamar a funciones en Chrome si son virtuales.

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

Así que digamos que tenemos una instancia de Chrome, y que llamamos un par de funciones:

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

El error de puntero nulo consigo siempre que llame funciones virtuales es:

  

Programa recibió EXC_BAD_ACCESS señal, no se pudo acceder a la memoria.   Motivo: KERN_PROTECTION_FAILURE en la dirección: 0x00000008

¿Alguna idea de lo que está pasando?

Actualización: Como muchos de ustedes han señalado - el código funciona realmente. Lamentablemente no puedo dar un ejemplo más completo, ya que el código es más profundo de WebCore (WebKit). Sin embargo, he reducido el problema. Si creo una instancia de Chrome manualmente, llamada Funciones virtuales funcionan. Así que el problema está en este caso particular, el cromo - no puede crear instancias correctamente. Ahora, la instancia de Chrome se instancia en un constructor de otra clase. Voy a investigar más ...

Actualización 2: Ok, el examen de la viable en la instancia infractor demuestra que es nula; de GDB:

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

Una instancia normal tiene una vtable correcta. Por lo tanto, tengo que averiguar por qué la viable es nulo - Me pregunto cómo puede pasar? Tal vez porque está siendo instanciado en algunas otras clases Constructor?

Actualización 3: Parece que estoy correcta sobre el tema que se está instancias dentro de otro constructor de la clase.

Así que, antes de la creación de instancias se veía así:

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

Y m_chrome es una instancia válida, con un vtable nula. He cambiado la creación de instancias por lo que sucede cuando la primera vez que se necesita la variable (esto implica guardar ChromeClient para más tarde):

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

Ahora la instancia :: Página cromo () es el correcto, con la viable adecuado - bastante extraño

!

Actualización 4: Última actualización, lo prometo :). Ok, así que he señalado es exactamente. Se obtiene la instancia correcta, con la viable, si se ejemplariza en el cuerpo Página del constructor. Si se ejemplariza en la cabeza Página del constructor, que no tiene un vtable. ¿Hay alguna limitación en los tipos de variable de ajuste que se puede hacer en la cabeza de un constructor? Creo que eso es otra cuestión Stackoverflow.

Gracias a todos por ser tan útil.

¿Fue útil?

Solución

Sí, el este puntero es cero. Añadir 8 para obtener una compensación, y no es su culpa. Evidentemente, usted no tiene ningún objeto real en absoluto.

Ya que no han publicado código suficiente para llegar realmente a los apretones, supongo. la totalidad o bien este puntero es 0, o el puntero de la tabla de función virtual es 0, tal vez porque el objeto ha sido eliminado después de su creación y antes de intentar llamarlo.

El mejor consejo que te puedo dar es crear un mucho más pequeño tubo de ensayo. Ya sea que usted encontrará su problema o que va a terminar con un ejemplo contabilizable.

El VTBL no está en su lugar en una instancia hasta el final del proceso de construcción. De hecho, la especificación requiere la modificación progresiva de la VTBL para que coincida con el estado de la construcción de la jerarquía de clases.

Otros consejos

Se puede publicar el código completo?

Después de una ligera modificación en el código (lo que está disponible), funciona:

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

No estoy familiarizado con la base de código que tiene, pero no debería escribir lo siguiente:

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

en lugar de:

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

ssume su no copiables son los siguientes (al menos para la mía)

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

después de insertar público modificador a la función de la clase de cromo y alguna implementación ficticia para ellos, todo funcionó sin problema planteado.

  
    
      

no hay problema con el código publicado, podría ser que está haciendo las cosas mal y no publicar los parte aquí.

    
  

Por último, no comprobación de error de asignación. (Sí, "nuevo" son la asignación en el montón)

he encontrado que esto fue causado por permitir que todos los símbolos a ser exportados.

Por lo general, WebCore sólo tiene un subconjunto de símbolos exportados -. Básicamente en las cosas que las necesidades WebKit

He cambiado eso para exportar todos los símbolos - y de alguna manera causó este error

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top