【问题标题】:Losing member data when creating a thread创建线程时丢失成员数据
【发布时间】:2023-03-18 19:25:01
【问题描述】:

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

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-&gt;name),但问题是一样的。我最好的猜测是我的args_struct 错误地处理了变量,但我不知道为什么它只会在部分时间失败。

如何在mythreadfunc 中获得正确的变量值?

【问题讨论】:

    标签: c++ c multithreading pthreads


    【解决方案1】:

    在堆上为您的新线程创建参数,它超出了调用函数的范围,因此对您的线程无效:

    struct arg_struct *arg1 = new arg_struct;
    
    args1->num_req = n;
    // etc...
    
    pthread_create(&p1, NULL, &mythreadfunc, (void *) args1);
    

    【讨论】:

    • 在 C++ 中,在包含 std::string 的结构上使用 malloc 是错误的(即在非 POD 结构上),应该使用 new arg_struct *arg1 = new arg_struct; 请注意 Nibirue 似乎有点困惑他的代码是 C 还是 C++。
    • @jahhaj 谢谢,错过了他在那里使用string,但从他在arg中的分配中应该很明显。更新了答案
    • @jahhaj,不,这不是错误,malloc 只是创建了一块内存,这很好。在不构造对象(即初始化内存)的情况下开始使用对象是错误的,这可以通过使用placement new来完成。
    • @Jonathon Wakely,你当然是对的,但为了简洁起见,我忽略了这种可能性。
    【解决方案2】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多