Pergunta

Como você pode ver no código abaixo, tenho uma classe base abstrata "HostWindow" e a classe que deriva dela "Chrome". Todas as funções são implementadas no Chrome. A questão é que não posso chamar funções no Chrome se forem virtuais.

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

Então, digamos que temos uma instância do Chrome e chamamos algumas funções:

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

O erro de ponteiro nulo que recebo sempre que chamo de funções virtuais é:

Programa recebido Signal exc_bad_access, não pôde acessar a memória. Motivo: Kern_protection_failure no endereço: 0x00000008

Alguma ideia do que está acontecendo?

Atualizar:Como muitos de vocês apontaram - esse código realmente é executado. Infelizmente, não posso fornecer um exemplo mais completo, pois o código está profundamente dentro da webcore (webkit). No entanto, reduzi o problema. Se eu criar uma instância do Chrome manualmente, chamando as funções virtuais funcionam. Portanto, o problema é com esta instância do Chrome específica - ela não pode instanciar corretamente. Agora, a instância do Chrome é instanciada em um construtor de outra classe. Vou investigar mais ...

Atualização 2:OK, examinar o VTable na instância ofensiva mostra que é nulo; do GDB:

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

Uma instância normal tem um VTable correto. Então, eu tenho que descobrir por que o VTable é nulo - eu me pergunto como isso pode acontecer? Talvez porque esteja sendo instanciado em algumas outras classes construtor?

Atualização 3:Parece que estou correto sobre o problema ser sua instanciação dentro do construtor de outra classe.

Então, antes da instanciação parecia assim:

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

E M_CHROME é uma instância inválida, com um nil vtable. Eu mudei a instanciação para que isso acontece quando a primeira vez a variável é necessária (isso envolve salvar o cromecliente para mais 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;
}

Agora, a instância da página :: Chrome () é a correta, com o vtable adequado - bastante estranho!

Atualização 4:Última atualização, prometo :). Ok, então eu identifiquei exatamente isso. Você obtém a instância correta, com o VTable, se você a instanciar no corpo do construtor da página. Se você o instanciar na cabeça do construtor da página, ele não possui um vtable. Existe alguma limitação nos tipos de configuração variável que você pode fazer na cabeça de um construtor? Eu acho que essa é outra questão de Stackoverflow.

Obrigado pessoal por serem tão úteis.

Foi útil?

Solução

Sim, o ponteiro 'este' é zero. Adicione 8 para obter um deslocamento, e há sua culpa. Aparentemente, você não tem nenhum objeto real.

Já que você não postou código suficiente para realmente entender, acho. O inteiro deste ponteiro é 0 ou o ponteiro da tabela de função virtual é 0, talvez porque o objeto tenha sido excluído depois que foi criado e antes de tentar chamá -lo.

O melhor conselho que posso dar é criar um tubo de teste muito menor. Ou você encontrará seu problema ou acabará com um exemplo postável.

O VTBL não está em vigor em uma instância até o final do processo de construção. De fato, as especificações requerem modificação progressiva do VTBL para corresponder ao estado de construção da hierarquia de classes.

Outras dicas

Você pode postar o código completo?

Após uma pequena modificação em seu código (o que quer que esteja disponível), ele 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;
}

Não estou familiarizado com a base de código que você tem, mas você não deve escrever o seguinte:

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

ao invés de:

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

ssume o seu não copiável é o seguinte (pelo menos para o meu)

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

Depois de inserir público Modificador para a função de classe do Chrome e alguma implementação fictícia para eles, tudo funcionou sem problemas declarados.

Não há problema com o código postado, pode ser que você esteja fazendo as coisas erradas e não publicando essas partes aqui.

Por fim, faça a verificação da falha de alocação. (Sim, "novo" é alocação na pilha)

Descobri que isso estava sendo causado ao permitir que todos os símbolos fossem exportados.

Geralmente, a webcore possui apenas um subconjunto de símbolos exportados - basicamente em coisas que o Webkit precisa.

Mudei isso para exportar todos os símbolos - e de alguma forma causou esse erro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top