2012-03-06 133 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