2012-03-06 142 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析構函數中發生崩潰的部分聽起來像可能是猜測。 – 2012-03-07 00:03:33

+0

@MultimediaMike當然哦!我忘了放入gdb輸出。我將編輯該問題以顯示此內容。 – 2012-03-07 00:19:21

+0

'this'指針看起來確實錯了(包含-64)。我會說你找到了原因。你只需要弄清楚它是如何進入該狀態的。 – 2012-03-07 00:37:59

回答

1

你使用return_value的方法是錯誤的:

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,如果你是在什麼線程要加入通行證pthread_exit()(或等價什麼線程函數返回不感興趣):

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

謝謝!我不確定如果沒有其他人看過它,我會發現它。我們的技術援助對這類事情確實毫無價值。 – 2012-03-07 03:29:39