문제

아래 코드에서 볼 수 있듯이, 나는 추상적 인 기본 클래스 "Hostwindow"와 "Chrome"에서 파생되는 클래스가 있습니다. 모든 기능은 Chrome에서 구현됩니다. 문제는 Chrome에서 가상이라면 기능을 호출 할 수 없다는 것입니다.

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

Chrome 인스턴스가 있다고 가정 해 봅시다. 몇 가지 기능을 호출합니다.

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

가상 함수를 호출 할 때마다 얻을 수있는 null 포인터 오류는 다음과 같습니다.

프로그램 수신 신호 exc_bad_access, 메모리에 액세스 할 수 없습니다. 이유 : 주소의 Kern_Protection_Failure : 0x00000008

무슨 일이 일어나고 있는지 아십니까?

업데이트:많은 분들이 지적 했듯이이 코드는 실제로 실행됩니다. 불행히도 코드가 웹 코어 (WebKit) 내부에 있기 때문에 더 완전한 예를 제공 할 수 없습니다. 그러나 나는 문제를 좁혔다. 크롬 인스턴스를 수동으로 만들면 가상 기능을 호출하십시오. 따라서 문제는이 특정 크롬 인스턴스와 관련이 있습니다. 제대로 인스턴스화 할 수 없습니다. 이제 크롬 인스턴스는 다른 클래스의 생성자로 인스턴스화됩니다. 더 조사하겠습니다 ...

Update 2:자, 불쾌한 인스턴스에서 vtable을 검토하면 그것이 널이라는 것을 보여줍니다. GDB에서 :

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

일반 인스턴스에는 올바른 vtable이 있습니다. 그래서, 나는 왜 vtable이 nil인지 알아 내야합니다. 어떻게 일어날 수 있는지 궁금합니다. 어쩌면 다른 클래스 생성자에서 인스턴스화되어 있기 때문일 수 있습니까?

3 : 업데이트 3.다른 클래스의 생성자 내부의 인스턴스화라는 문제에 대해 내가 맞는 것 같습니다.

따라서 인스턴스화가 다음과 같이 보였습니다.

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

그리고 m_chrome은 nil vtable이있는 잘못된 인스턴스입니다. 인스턴스화를 변경하여 변수가 처음 필요할 때 발생합니다 (이는 나중에 크로마 클리어를 저장하는 것이 포함됩니다).

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

이제 페이지 :: chrome () 인스턴스는 올바른 vtable과 함께 올바른 것입니다.

Update 4:마지막 업데이트, 나는 약속 :). 좋아, 그래서 나는 그것을 정확히 지적했다. 페이지 생성자의 본문에 인스턴스화하면 vtable을 사용하면 올바른 인스턴스를 얻습니다. 페이지 생성자의 헤드에 인스턴스화하면 vtable이 없습니다. 생성자의 헤드에서 할 수있는 변수 설정 유형에 제한이 있습니까? 나는 그것이 또 다른 stackoverflow 질문이라고 생각합니다.

너무 도움이되어 주셔서 감사합니다.

도움이 되었습니까?

해결책

예, '이'포인터는 0입니다. 오프셋을 얻으려면 8을 추가하면 잘못이 있습니다. 당신은 분명히 실제 객체가 전혀 없습니다.

당신은 실제로 그립에 올 수있는 충분한 코드를 게시하지 않았기 때문에, 나는 추측하고 있습니다. 이 포인터 전체가 0이거나 가상 함수 테이블 포인터가 0이므로, 객체가 생성 된 후 및 호출을 시도하기 전에 객체가 삭제 되었기 때문일 수 있습니다.

내가 줄 수있는 가장 좋은 조언은 훨씬 작은 테스트 튜브를 만드는 것입니다. 당신은 당신의 문제를 찾을 수 있거나 사례 예로 끝날 것입니다.

VTBL은 건설 과정이 끝날 때까지 인스턴스에 제자리에 있지 않습니다. 실제로, 사양은 클래스 계층 구조의 구성 상태와 일치하기 위해 VTBL의 점진적인 수정이 필요합니다.

다른 팁

전체 코드를 게시 할 수 있습니까?

코드를 약간 수정 한 후 (사용 가능한지) 작동합니다.

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

나는 당신이 가진 코드 기반에 익숙하지 않지만 다음을 작성해서는 안됩니다.

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

대신에:

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

당신의 보조 불가능한 것은 다음과 같습니다 (적어도 나의 경우)

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

삽입 후 공공의 클래스 크롬의 기능과 그에 대한 더미 구현에 대한 수정자는 모든 것이 언급 된 문제없이 효과가있었습니다.

게시 된 코드에는 아무런 문제가 없습니다. 문제가 발생하고 있으며 여기에 해당 부분을 게시하지 않을 수도 있습니다.

마지막으로 할당 실패를 확인하십시오. (예, "새로운"는 힙에 할당됩니다)

나는 이것이 모든 기호를 내보낼 수있게함으로써 발생한다는 것을 알았습니다.

일반적으로 WebCore는 기본적으로 WebKit이 필요로하는 것들에 대해 내보낸 기호의 하위 집합 만 있습니다.

모든 기호를 내보내기 위해 변경했습니다. 어떻게 든이 오류가 발생했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top