2014-02-07 3 views
1

그래서 세 가지 클래스가 있습니다. 하나의 메인 클래스, ClassA, 하나의 기본 클래스, ClassB, 그리고 하나의 상속 된 클래스, ClassC가 함께 작동하지만, 프로그램을 닫으면 'Access violation writing location'오류가 발생합니다. 그래서 난 단지 클래스 C에게닫을 때 액세스 위반 오류가 발생했습니다.

를 게시 할 예정입니다 단지 기본 클래스

를 ClassA .H

ClassA 
{ 
public: 
    ClassA(void) : player_(NULL), bullet_(NULL) {}; 
    ~ClassA(void); 

    void Update(); 
    void fireBullet(int posx, int posy, int speed); 

private: 
    ClassB* player_; 
    ClassB* bullet_; 
}; 

를 ClassA의 .CPP

void ClassA::Update() 
{ 
    ClassA* pointer = this; 
    player_->Update(*pointer); 

    if(bullet_->IsAlive()) 
     bullet_->Update(*pointer); 
} 

void fireBullet(int posx, int posy, int speed) 
{ 
    //make it active, set its position and speed 
} 

클래스 B입니다 : 여기

는 설정이다

클래스 C .h

ClassC : public ClassB 
{ 
public: 
    ClassC() : posx_(0), posy_(0) {}; 
    virtual void Update(ClassA &a); 

private: 
    int posx_; 
    int posy_; 
} 

ClassC의 .CPP

void ClassC::Update(ClassA &a) 
{ 
    if(spacebar == pressed) 
     a.fireBullet(posx_, posy_, 10); 
} 

은 내가 어딘가에 참조하는 오류를 느낄하지만 난 어디 있는지 알고하지 않습니다. 이 문제는 글 머리 기호가 생성 될 때만 발생하므로 프로그램 전체에서 스페이스 바를 누르지 않고 프로그램을 닫지 않으면 프로그램이 정상적으로 종료됩니다. 그러나 런타임에 스페이스 바를 누르면 액세스 위반 오류가 발생합니다. ClassA 소멸자를 확인했지만 소멸자에 무언가가 있는지 여부에 관계없이 문제가 발생합니다.

관련 코드 만 표시하려고했습니다. bullet_ 및 player_를 초기화하는 데 사용되는 initialse 함수가 있지만 문제와 관련성이없는 것은 아닙니다.

소멸자 :

를 ClassA 를 ClassA : ~를 ClassA (무효) { player_을 삭제; 삭제 bullets_; }

ClassB가와 ClassC

~Class {}; 
또한

player_ 및 bullet_이를 ClassA에서 함수에 초기화됩니다 나는 알 수

ClassA::Initialise() 
{ 
    ClassB* player = new ClassC; 
    player->Initialise(); 
    player_ = player; 

    ClassB* bullet = new ClassD; //ClassD is also inherited from B 
    bullet->Initialise(); 
    bullet_ = bullet; 
} 
+1

언제 포인터에 개체에 * 유효한 * 주소를 할당합니까? * Class *가 * by by value assignment 또는 copy-construction에 나타나면, [Rule of Three] (http://en.wikipedia.org/wiki/Rule_of_three_ (C % 2B % 2B_programming)) 미준수. 코드를주의 깊게 확인하십시오 (또는 더 나은 점은 스마트 포인터를 사용하면 걱정할 필요가 없습니다). 대부분은 모두 디버거를 연결하고 * debug * this를 사용합니다. 당신이 당신이 어디에 있는지 어떻게 알 수있는지를 꽤 많이 알려주는 호출 스택을 가지고 행복하게 던질 것입니다 (여러분이 스택을 손상시키지 않는다고 가정 할 때). – WhozCraig

+0

A, B, C의 소멸자를 볼 수 있습니까? – IdeaHat

+0

Linux를 사용하는 경우 Valgrind에서 프로그램을 실행할 수 있습니까? http://valgrind.org/docs/manual/quick-start.html – nodakai

답변

0

하나의 실수 당신이 ClassC에서 참조를 ClassA를 보낼 것입니다 : : 업데이트 (ClassA & a) 그리고 포인터로 사용하십시오. 당신의 생성자, 소멸자, 객체 생성에 대한 코드를 보내 주시기 바랍니다, 또한

void ClassC::Update(ClassA &a) 
{ 
    if(spacebar == pressed) 
     a.fireBullet(posx_, posy_, 10); 
} 

작성 시도 등의 프로그램이 종료 후 액세스 위반을 얻을 수

+0

이 게시물에 오타가 있습니다. 실제로 도트 연산자 인 – Daniel

0

때문이다. 오류가 소멸자에 있음을 의미합니다. 때로는 소멸자가 명시 적 호출없이 호출됩니다. 그러나 당신이 게시 한 파일에는 숨겨진 호출이 있습니다. 그것은 오류가 소멸자에 있음을 의미합니다.

ClassA ClassA:: ~ClassA(void) 
{ 
    delete player_; 
    delete bullets_; 
} 

이 코드는 문제를 일으킬 수 있습니다. 포인터가 nullptr이거나 일부 쓰레기이기 때문에 액세스 위반이 발생합니다. 그것을 피하기 위해, 나는 그들을 검사하는 것이 좋습니다.이 코드는 정말 보호 만드는 그러나

ClassA ClassA:: ~ClassA(void) 
{ 
    if (player_) 
    {  
     delete player_; 
     player_ = nullptr; // or NULL if it's not c++0x 
    } 
    if (bullets_) 
    { 
     delete bullets_; 
     bullets_ = nullptr; 
    } 
} 

, 당신은
1.Set 그들을 불러 그들에 삭제 한 후 삭제 2. 그들이 다른 곳 nullptr하는 생성자
에서 nullptr 할 수 있어야합니다.

그게 전부입니다. 도움이되면 답장하십시오.

MarkGrin

+0

을 사용하면 null 포인터를 삭제하는 것이 표준에 의해 지원되며 아니야. (C에서'free (NULL)'이 지원되는 것처럼). – WhozCraig

+0

0으로 설정하고 확인하는 주된 아이디어는 nullptr 삭제를 피하는 것이 아니라 미리 설정되지 않은 포인터로 삭제 된 변수 또는 삭제를 방지하기위한 것입니다. 그래서 nullptr을 삭제해도 괜찮지 만 포인터를 확인하고 생성자와 삭제 후 nullptr로 설정하여 이전에 삭제 된 변수 또는 삭제가 설정되지 않은 포인터로 삭제되지 않도록해야합니다. 괜찮습니까? @peter – user3164888

관련 문제