创建线程时丢失成员数据

时间:2012-07-28 21:36:43

标签: c++ c multithreading pthreads

我发现很难解释这个问题,所以我会发布代码并解释会发生什么,然后问如何让它做我想做的事情。首先,我在子进程中创建一个线程:

pid_t childpid = fork();

if(childpid == -1){
  cout << "Failed to fork." << endl;   
}
else if(childpid == 0){     
  //request threads
  pthread_t p1, p2, p3;          

  struct arg_struct args1, args2, args3;

  args1.name = "data Joe Smith";
  args1.num_req = n;
  args1.buff_size = b;
  pthread_create(&p1, NULL, &mythreadfunc, (void *)&args1);   
}

这是struct arg_struct

struct arg_struct{
    string name;
    int num_req;
    int curr_value;
    int buff_size;
};

mythreadfunc:

void *mythreadfunc(void *arguments){ 
    struct arg_struct *args = (struct arg_struct *)arguments;
    string local_name = args->name;     
    int local_num_req = args->num_req;
    //request new thread
    RequestChannel chan("control", RequestChannel::CLIENT_SIDE);
    cout << "done." << endl;
    string reply1 = chan.send_request("newthread");

    cout << "Reply to request 'newthread' is " << reply1 << "'" << endl;

    RequestChannel chan2(reply1, RequestChannel::CLIENT_SIDE); 

    cout<<"local_name:  "<<local_name<<endl;    //returns incorrect value***
    cout<<"local_num_req:  "<<local_num_req<<endl;  //returns incorrect value***

    //close up all channels
    string reply2 = chan2.send_request("quit");
    cout << "Reply to request 'quit' is '" << reply2 << "'" << endl;
    string reply3 = chan.send_request("quit");
    cout << "Reply to request 'quit is '"<< reply3 << "'" << endl;
}

在使用local_namelocal_num_req的两行中,存在问题。我编译得很好,但这两个变量似乎每次都存储不同的东西。有时候它可以正常工作,有时候它们会保存垃圾值,程序永远不会执行它们(或者后续的任何操作)。我尝试使用没有局部变量的原始名称(即args->name),但问题是相同的。我最好的猜测是我的args_struct处理错误的变量,但我不知道为什么它只会在一段时间内失败。

如何在mythreadfunc中找到正确的变量值?

2 个答案:

答案 0 :(得分:8)

在堆上创建新线程的参数,它在调用函数中超出范围,因此不适用于您的线程:

struct arg_struct *arg1 = new arg_struct;

args1->num_req = n;
// etc...

pthread_create(&p1, NULL, &mythreadfunc, (void *) args1);

答案 1 :(得分:1)

创建新主题后,

p1args1都会超出范围,因此在mythreadfunc运行时它们不再存在。

要修复代码,您需要使这些对象的生命周期长于使用它们的新线程的生命周期。这可以通过在堆上创建对象,或者通过在封闭范围内创建它们来确保它们在新线程完成之前不会超出范围来完成:

pthread_t p1, p2, p3;
struct arg_struct args1, args2, args3;

pid_t childpid = fork();

if(childpid == -1){
  cout << "Failed to fork." << endl;   
}
else if(childpid == 0){     
  //request threads

  args1.name = "data Joe Smith";
  args1.num_req = n;
  args1.buff_size = b;
  pthread_create(&p1, NULL, &mythreadfunc, (void *)&args1);   
}

// ...

void* res = pthread_join(&p1);

// safe for `args1` to go out of scope now