2014-02-07 57 views
1

所以我有3个类。一个主要的类,ClassA,一个基类,ClassB和一个继承类ClassC,然而,当我关闭我的程序时,我得到了'访问冲突写入位置'错误。关闭时出现访问冲突错误

这里是设置:

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类

Class 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_,但并不认为它与问题相关。

析构函数:

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

在什么时候你将*有效的地址赋值给所有这些指针的对象?如果'A类'出现在任何*按值赋值或复制构造中,我将使用[Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B% 2B_programming))违规。仔细检查您的代码(或更好地使用智能指针,这样您就不必担心它)。最重要的是附加一个调试器和* debug *这个。它会很高兴地通过一个调用堆栈吐出你的脸,告诉你几乎是如何到达你的位置(假设你没有损坏堆栈)。 – 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

woops typo in the post,I am实际上使用点运算符 – Daniel

0

,因为你的程序得到访问冲突结束后。这意味着错误在析构函数中。有时析构函数在没有明确调用的情况下被调用。但是,在您发布的文件中,现在存在这种隐藏的调用。这意味着错误在你的析构函数中。

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

所以这个代码可能会导致问题。因为如果指针是空的或只是一些垃圾,就会有访问冲突。为了避免它,我建议检查它们。

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.设置他们nullptr在构造
2.设置他们nullptr其他地方呼唤他们删除了。

就是这样。如果有帮助,请回复。

MarkGrin

+0

删除一个空指针是由标准支持的,并减少到一个没有操作。 (就像C中支持'free(NULL)'一样)。 – WhozCraig

+0

将它们设置为零并检查的主要思想不是避免删除nullptr,而是防止删除以前删除的变量或删除未指定的指针。所以当然可以删除nullptr,但是你必须检查指针,并在构造函数中将它们设置为nullptr,并在删除之后,以防止删除以前删除的变量或删除未指定的指针。可以吗?@peter – user3164888