2011-01-22 7 views
1

同じクラスのメソッドからクラスのメンバーにアクセスしようとするとセグメンテーションが発生しますが、それはまったく意味がありません。Segfault使用時* this

私はTreeクラスがあります。

class Tree 
{ 

public: 

Coord* root; 

Tree(int x, int y) 
{ 
    root = new Coord(x, y); 
    populateTree(); 
} 

void populateTree() 
{ 
    queue<Coord*> nodes; 
    nodes.push(root); 

    while (nodes.size() > 0) 
    { 
     Coord* currnode = nodes.front(); 
     nodes.pop(); 

     if (!(currnode->getValidMoves())) 
     { 
      return; 
     } 

     else 
     { 
      for (int i = 0; i < MAX_CHILDREN_PER_COORD; i++) 
      { 
       if (currnode->children[i] != NULL) 
       { 
        nodes.push(currnode->children[i]); 
       } 
      } 
     } 
    } 
} 

...とCOORDクラス...

class Coord : public Loc 
{ 
    public: 

    Coord(int xPos, int yPos); 

    Coord* children[MAX_CHILDREN_PER_COORD]; 


    bool getValidMoves(); 


    bool operator==(Coord coord); 
    bool operator==(Loc loc); 

}; 

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos) {} 


bool Coord::getValidMoves() 
{ 
    //This line segfaults 
    Coord test = *this; 

    //Global boolean method. Checks found 
    if (!foundTrue()) 
    { 
     for (int i = 0; i < MAX_CHILDREN_PER_COORD; i++) 
     { 
      //If the above segfaulting line is commented out, this is the first place that segfaults 
      int newX = x + knightPositions[i].x; 
      int newY = y + knightPositions[i].y; 

      if (!(newX > GRID_X || newX < 0 || newY > GRID_Y || newY < 0)) 
      { 
       //knightPositions is a Loc array of length MAX_CHILDREN_PER_COORD 
       children[i] = new Coord(x + knightPositions[i].x, y + knightPositions[i].y); 
       //Global 2d array of ints. Gets checked by foundTrue() 
       found[x + knightPositions[i].x][y + knightPositions[i].y] = true; 
      } 
     } 

     return true; 
    } 

    else 
    { 
     return false; 
    } 

    //Otherwise, just leave it as a blank array 
} 


bool Coord::operator==(Coord coord) 
{ 
    return coord.x == x && coord.y == y; 
} 

bool Coord::operator==(Loc loc) 
{ 
    return loc.x == x && loc.y == y; 
} 

...とのLocクラスからCOORDのinheirits ...

class Loc 
{ 
    public: 
     int x, y; 

     //Constructor 
     Loc(int xPos, int yPos) : x(xPos), y(yPos) {} 
}; 

segfaultは、コメントによって示されるように、Coord :: getValidMoves()で発生します。そのコードをステップ実行して* thisまたはxまたはthis-> xを監視すると、「0xbaadf00dでメモリにアクセスできない」というメッセージが表示されます

なぜこのようなことが起こりますか?私はどこを台無しにしましたか?メソッドで*これをアクセスしようとするとsegfaultが発生する可能性があります。

+0

オブジェクトがそのメソッドの実行中にオブジェクトを削除していますか(同じスレッド内の別のスレッドまたは別のコールバック)ですか? –

+0

最適化を有効にしていますか? – Omnifarious

+0

補足として、あなたは(Coord test = * this; '、' bool Coord :: operator ==(Coord coord) ')をいくつかの場所に'初期化されていない)ポインタメンバーはコピーctor(またはassigment opまたはdestructor)はありません。 –

答えて

4

Coord::childrenの要素を初期化する必要があります。それらはNULLであることが保証されていないので、populateTree()では、それぞれの子に対してヌルテストを実行すると、有効なCoordを指していませんが、nullではない子を取得します。それらがキューからポップされ、getValidMoves()を無効なCoordにコールすると、seg-faultが発生します。

変更へCoordコンストラクタ:あなたはstd::fillため#include <algorithm>する必要があります

注それはあなたがしようと、初めてだからセグメンテーション違反が間接参照thisへの試行で発生していること

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos) 
{ 
    std::fill(children, children + MAX_CHILDREN_PER_COORD, NULL); 
} 

(。無効なメモリにアクセスする

+0

それを修正します。本当にありがとう! – Lewis

1

無効な(または無効化された)ポインタでメソッドが呼び出されると、データメンバにアクセスする際のsegfaultがよくある問題です。言語はオブジェクトとメソッドの抽象化を提供しますが、基本的な実装には関数とデータがあります。メソッドはデータに適用される関数(コード)です(暗黙的に*this)。それは確かに問題があるとして、ポインタが、メソッドを呼び出す前に(nullではない、解放されません)有効であることを

チェックイン:上記のコードで

struct test { 
    int x; 
    void foo(int y) { 
     x = y;  // [1] 
    } 
}; 
int main() { 
    test *p = 0; 
    //p->foo();  // segfault in x=y above: this == 0 
    p = new test; 
    p->foo(); 
    delete p; 
    // p->foo(); // undefined behavior, can be a segfault or not 
    p = reinterpret_cast<test*>("This is a literal"); 
    p->foo();  // undefined behavior, probably segfault 
        // writing to read-only memory (this depends on compiler/environment) 
} 

、すべてのエラーは、ほとんどのラインで検出されますあなたのコンストラクタはこのように見えるようにした場合、[1]

0

としてマーク:

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos) 
{ 
    for (int i = 0; i < MAX_CHILDREN_PER_COORD; ++i) { 
     children[i] = NULL; 
    } 
} 

あなたの問題が離れて行くでしょう。コンストラクタ内のすべてのデータメンバーを初期化する必要があります。

問題は、childrenにランダムなデータが含まれることです。 NULLに初期化されないため、テストcurrnode->children[i] != NULLは、存在しない子に対しても真ではありません。これらの存在しない子要素のメンバ関数を呼び出すと、そのメンバ関数が実行されるとき無効なthisポインタがあります。