2012-07-28 18 views
0

我發現很難解釋這個問題,所以我會發布代碼並解釋發生了什麼,然後詢問如何讓它按照我想要的做。首先,我創建一個線程子進程中:創建線程時丟失成員數據

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中獲得正確的變量值?

回答

8

創建堆上的新線程的說法,它是走出去的調用函數的範圍,因此是無效的使用由你的線程(S):

struct arg_struct *arg1 = new arg_struct; 

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

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

在C++中,它是用一個錯誤malloc在包含std :: string的結構上(即在非POD結構上),應該使用new來代替'arg_struct * arg1 = new arg_struct;'注意Nibirue對於他的代碼是C還是有點困惑或者C++。 – jahhaj 2012-07-28 21:50:46

+0

@jahhaj謝謝,錯過了他在那裏使用'string',但應該從他在arg中的賦值中顯而易見。更新了答案 – pb2q 2012-07-28 21:52:22

+0

@jahhaj,不,這不是錯誤,'malloc'只是創建一塊內存,沒關係。開始使用該對象而不構建它(即初始化內存)可能會通過使用新的位置來完成是錯誤的。 – 2012-07-28 21:56:05

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