2012-03-06 2 views
1

나는 스레딩과 pthreads와의 동기화를 다루는 과제를 수행하고있다. 예제 코드에서 주 스레드는 잘 실행되는 두 개의 다른 스레드를 생성합니다. 두 "자식"스레드가 종료 될 때까지 주 스레드는 차단됩니다. 적어도, 이것이 내가 그것을 이해하는 방법입니다. 주 스레드가 실행을 다시 시작하면 AvionicsTask에 대한 소멸자를 호출 할 때 세그먼트 화 오류가 발생하는 것 같습니다. 솔직히, 나는 뭔가를 올바르게 초기화하지 않을 수도 있다는 것을 제외하고는 왜 그런지 전혀 모른다. 여하튼, 코드는 다음과 같다 :왜 Seg Fault가 발생합니까?

Task.h :

class Task { 
protected: 
    /* -- NAME */ 
    static const int MAX_NAME_LEN = 15; 
    char name[MAX_NAME_LEN]; 

    /* -- IMPLEMENTATION */ 
    pthread_t thread_id; 

public: 
    /* -- CONSTRUCTOR/DESTRUCTOR */ 
    Task(const char _name[]) { 

     std::strncpy(name, _name, MAX_NAME_LEN); 
    } 
    ~Task(){} 
    /* -- ACCESSORS */ 
    char * Name(); 

    virtual void Start();  
    virtual void Run()= 0; 
    static void GracefullyExitMainThread(); 
}; 

Task.cpp :

#include "task.h" 

std::vector<pthread_t> tasklist;  //keep track of tasks created 

void * thunkfunc(void * args) { 
     Task * task_instance = (Task *)args; 
     task_instance->Run(); 
     return NULL; 
} 

void Task::Start(){ 
    pthread_t threadmachine; 
    void * start_arg = NULL; 
    pthread_create(&threadmachine, NULL, thunkfunc, this); 
    tasklist.push_back(threadmachine); 
} 

void Task::GracefullyExitMainThread() { 
    void** return_value;    //unused 
    for(int i = 0; i < tasklist.size(); i++){ 
     pthread_join(tasklist[i], return_value); 
    } 
} 

char * Task::Name(){ 
    return name; 
} 

Task_Test_step1.cpp :

#include <iostream> 
using namespace std; 
#include "task.h" 


class RudderController : public Task { 
public: 
    RudderController(char _name[]) : Task(_name) {} 

    void Run() { 
    cout << "Rudder Controller [" << name << "] running\n" << flush; 
    for (int i = 0; i < 10; i++) { 
     cout << name << " waiting for next sensor input\n" << flush; 
     usleep(1000000); 
     cout << name << " issueing rudder control command" << i << "\n" << flush; 
     usleep(10000); 
    } 
    } 
}; 

class AvionicsTask : public Task { 
public: 
    AvionicsTask(char _name[]) : Task(_name) {} 

    void Run() { 
    cout << "Avionics System [" << name << "] running\n" << flush; 
    for (int i = 0; i < 10; i++) { 
     cout << name << " waiting for next refresh interval\n" << flush; 
     usleep(700000); 
     cout << name << " refreshing avionics screen " << i << "\n" << flush; 
     usleep(12000); 
    } 
    } 
}; 

int main(int argc, char * argv[]) { 

    /* -- CREATE TASKS */ 
    RudderController task1("rudder control"); 
    AvionicsTask  task2("avionics task"); 

    /* -- LAUNCH TASKS */ 
    task1.Start(); 
    task2.Start(); 

    Task::GracefullyExitMainThread(); 
} 

프로그램의 출력 gdb :

Starting program: /home/ben/Desktop/Part 1/test 
[Thread debugging using libthread_db enabled] 
[New Thread 0x7ffff707e700 (LWP 6797)] 
Rudder Controller [rudder control] running 
rudder control waiting for next sensor input 
[New Thread 0x7ffff687d700 (LWP 6798)] 
Avionics System [avionics task] running 
avionics task waiting for next refresh interval 
avionics task refreshing avionics screen 0 
... 
//more messages from the threads 
... 
avionics task refreshing avionics screen 9 
[Thread 0x7ffff687d700 (LWP 6798) exited] 
rudder control issueing rudder control command7 
rudder control waiting for next sensor input 
rudder control issueing rudder control command8 
rudder control waiting for next sensor input 
rudder control issueing rudder control command9 
[Thread 0x7ffff707e700 (LWP 6797) exited] 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000401ffa in AvionicsTask::~AvionicsTask (this=0xffffffffffffffc0, 
    __in_chrg=<optimized out>) at task_test_step1.cpp:21 
21 class AvionicsTask : public Task { 
+0

이것을 디버그 모드로 빌드하고 디버거를 통해 실행할 수 있습니까? 이것은 충돌에 대한 유용한 정보를 산출합니다. AvionicsTask 소멸자의 충돌에 관한 부분은 그것이 추측일지도 모르는 것처럼 들렸습니다. –

+0

@MultimediaMike 물론! 나는 gdb 출력을 넣는 것을 잊었다. 나는 그것을 보여주기 위해 질문을 편집 할 것이다. –

+0

'this'포인터가 정말 잘못 보입니다 (-64 포함). 너가 그 원인을 찾았다 고 말했을거야. 그 상태에 어떻게 도달하는지 알아 내면됩니다. –

답변

1

당신이 return_value를 사용하는 방법은 잘못된 것입니다 : 당신은 무엇 스레드 당신이 동등하게 pthread_exit()에 패스를 가입 (또는하는지 스레드 함수가 반환에 관심이 있다면

void** return_value;    
for(int i = 0; i < tasklist.size(); i++){ 
    pthread_join(tasklist[i], return_value); // <== return_value has an indeterminate value 
              // who knows where pthread_join() will write to? 
} 

그냥 NULL 전달) :

for(int i = 0; i < tasklist.size(); i++){ 
    pthread_join(tasklist[i], NULL); // <== ignore what the thread returns 
} 

당신은 이제까지 당신이 스레드에 의해 반환 된 값을 싶어처럼 보이는 것을 사용 결정하는 경우 :

void* return_value;    
for(int i = 0; i < tasklist.size(); i++){ 
    pthread_join(tasklist[i], &return_value); 

    // return_value contains the data the thread returned... 
} 
+0

감사합니다! 나는 다른 누군가가 그것을 보지 않고서는 그것을 잡을 수 있을지 확신하지 못합니다. 우리 TA는 이런 종류의 일에 정말로 가치가 없습니다. –

관련 문제