2011-01-22 6 views
1

같은 클래스의 메서드 내에서 클래스 멤버에 액세스하려고하면 segfault가 발생합니다.이 클래스는 전혀 의미가 없습니다.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]); 
       } 
      } 
     } 
    } 
} 

... 그리고 좌표 운전 클래스 ...

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 데이 클래스를하는 좌표 운전의 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)')에 대해'Coord'의 복사본을 만들고 있습니다. 초기화되지 않은) 포인터 멤버는 있지만 ctor (또는 assigment op 또는 destructor)는 없습니다. –

답변

4

Coord::children의 요소를 초기화해야합니다. 그들은 NULL이 아니므로 populateTree()에서 각 자식에 대해 null 테스트를 수행하면 유효한 Coord을 가리 키지 않더라도 null이 아닌 자식을 가져옵니다. 대기열에서 꺼내어 getValidMoves()Coord에 잘못 입력하면 seg-fault가 표시됩니다.

변경 Coord 생성자 :

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

(당신이 std::fill에 대한 #include <algorithm>하는 데 필요한 세그먼트 폴트가 역 참조 this에 시도에서 발생

참고 그건 당신이하려고 처음이기 때문. 잘못된 메모리에 액세스합니다.

+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) 
} 

, 모든 오류는 대부분의 라인에서 감지됩니다

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

문제는 멀리 갈 것입니다 : 당신이 당신의 생성자 모양과 같이 한 경우 [1]

0

로 표시. 생성자에서 모든 데이터 멤버를 초기화해야합니다.

문제는 children에 임의의 데이터가 포함됩니다. NULL으로 초기화되지 않으므로 존재하지 않는 자식에 대해서도 currnode->children[i] != NULL 테스트가 참이되지 않습니다. 그런 다음 존재하지 않는 자식에 대해 멤버 함수를 호출하고 해당 멤버 함수가 실행될 때 잘못된 this 포인터를 갖게됩니다.