2010-04-07 10 views
1

저는 C++을 처음 접했고 약간 문제가 있습니다. 다른 클래스의 메서드에 대한 호출에서 변수를 할당하려고하지만 항상 segfaults입니다. 내 코드는 경고없이 컴파일되고 gdb에서 모든 변수가 올바른지 확인했지만 함수 호출 자체가 segfault를 일으키는 것으로 보입니다. 제가 사용하는 코드는 대략 다음과 같습니다 :Segfault 메서드를 호출 할 때 C++

class History{ 
public: 
bool test_history(); 
}; 
bool History::test_history(){ 
    std::cout<<"test"; //this line never gets executed 
    //more code goes in here 
    return true; 
} 


class Game{ 
private: 
    bool some_function(); 
public: 
    History game_actions_history; 

}; 


bool Game::some_function(){ 

    return game_actions_history.test_history(); 

} 

어떤 조언이나 조언을 주시면 대단히 감사하겠습니다!

편집 : 더 이상 local_variable이없고 값이 직접 반환되도록 코드를 편집했습니다. 그러나 여전히 세그 폴트입니다. 실제 코드를 게시하는 경우 상당히 큰데, 어떤 부분을 게시해야합니까?

+7

우리는 실제 코드를 참조 할 필요가있다. –

+1

'local_variable'은별로 로컬하지 않습니다. 그렇습니까? :) 그것은 멤버 변수입니다. 또한, bool을 테스트하여 해당 bool을 반환하는 것은 약간 중복됩니다 :'return local_variable;'. 물론, 당신은 실제로 그것을 저장할 필요가 없다.'return game_actions_history.test_history();'어쨋든,이 코드는 "괜찮다". 'Game g;를 만들 수는 있지만'g.some_function();'을 호출 할 수는 없습니다. 그렇지 않은 경우 제대로 작동합니다. – GManNickG

+0

그리고 어떻게 부르니? – EFraim

답변

4

내가 본 것부터 표시 한 코드에는 아무런 문제가 없습니다. 그러나 segfaults는 종종 손상된 메모리를 가지고 있다는 좋은 징후입니다. 그것은 여러분이 보여준 것 외에 다른 곳에서 일어나고 있으며 여기서 코드에만 영향을줍니다. 배열, 포인터 또는 임의의 수작업 메모리 상호 작용을 처리하는 곳을 보게됩니다.

+0

나는 이것이 정확하게 일어난다 고 생각합니다. 방금 다른 기능을 포함하지 않는 코드의 단순화 된 버전을 만들었으며 문제없이 작동하는 것처럼 보였습니다. – shuttle87

+0

메모리 물건과 포인터를 다루는 코드를 게시하십시오. 이 포럼은 도움이됩니다. 나는 당신이 지금 거기에있는 것을 지우면 누구나 마음 먹을 것입니다. segfault 대신에 예외를 던질 수있는 방법을 보여줄 수도 있습니다. – wheaties

1

어두운 곳에서 촬영하십시오. (Game*)thisNULL입니까?

0

당신은 약간의 코드를 남겼다 고했습니다. 이 질문에 답하기 전에 모든 코드를 확인해야합니다.

1

코드는 문제가 없지만 예제가 너무 잘못되어 무엇이 잘못되었는지 설명 할 수 없습니다. 어떤 것들은 내가 좋을 것 :

각 클래스의 소멸자와 생성자에 출력물을 추가

Game::Game()    { cerr << this << " Game::Game" << endl; } 
Game::Game(Game const&) { cerr << this << " Game::Game(Game const&)" << endl; } 
Game::~Game()    { cerr << this << " Game::~Game" << endl; } 
bool Game::some_function() { cerr << this << " Game::some_function()" << endl; ... } 

이 공개됩니다

  • 널 객체 포인터를.
  • 클래스 포인터가 잘못되었거나 삭제되었습니다.

둘째, 디버깅을 위해 인쇄물을 cout 대신 cerr로 보내는 것이 좋습니다. cout은 일반적으로 출력되기 전에 (효율을 위해) 버퍼링되지만, cerr은 (적어도이 경우에 사용됩니다.) 출력되지 않습니다. 오류 처리기, at_exit 등을 실행하지 않고 프로그램이 종료되면 버퍼링되지 않고 즉시 인쇄되는 경우 출력을 볼 가능성이 높습니다.

세 번째로, 클래스 정의가 헤더에 존재하면 클래스 정의가 하나의 cpp 파일에 저장되고 다른 클래스에서는이 클래스를 사용하는 코드가 있으면 cpp 파일 중 하나라도 없으면 이런 종류의 충돌이 발생할 수 있습니다 헤더를 변경 한 후 다시 컴파일됩니다.

일부 다른 가능성은 다음과 같습니다

  • 스택 오버 플로우 : 당신 때문에 깊은 재귀의 스택에 많은 메모리를 할당했거나 (즉 생성되지 또는 로컬 변수로 대량의 데이터 배열을 포함하는 객체를 할당하는 new 또는 malloc이있는 힙)
  • 손상된 클래스 vtable (일반적으로 빌드 도구의 종속성 오류로 인해 가능)
  • 손상된 개체 vtable 포인터 : 포인터의 오용 : 삭제 된 메모리에 대한 포인터 사용 또는 잘못 사용중인 주소에 쓰기. 가상 함수가 없으므로 예제에서는 그렇지 않습니다.
  • 삭제 된 스택에 할당 된 객체에 대한 포인터 또는 참조를 유지하는 중입니다. 위의 출력 코드는이 경우를 보여줍니다.
+0

"[] 인쇄물을 cerr 대신 cout으로 보내면 cout 및 cerr을 전환했습니다. 그리고 예 cerr (아직) unbuffered입니다, 당신은 endl 함께 주위를 엉망 필요가 없다는 장점이 있습니다. – NomeN

+0

감사합니다. 고쳤다. – user48956

3

나는 많은 segfaults와 함께 valgrind을 성공적으로 사용했습니다.

그리고 segfault로 인한 코어 덤프로 gdb를 실행하려 했습니까? 남자 GDB에서 :

gdb program core 

가 코어 덤프를 만들려면 설정해야 할 수도 있습니다 :

ulimit -c unlimited 
관련 문제