1 //pthread_create()函數的錯誤示例 2 //新建線程同時傳入線程號、線程號總和和消息 3 #include <stdio.h> 4 #include <pthread.h> 5 #include <stdlib.h> 6 #define NUM_THREADS 8 7 8 void *PrintHello(void *threadid) 9 { 10 int *id_ptr, taskid; 11 sleep(1); 12 id_ptr=(int *)threadid; 13 taskid=*id_ptr; 14 printf("Hello from thread %d\n", taskid); 15 pthread_exit(NULL); 16 } 17 //int t; 18 int main(int argc, char const *argv[]) 19 { 20 pthread_t threads[NUM_THREADS]; 21 int rc; 22 int t; 23 24 for (t = 0; t < NUM_THREADS; ++t) 25 { 26 printf("Creating thread %d\n",t); 27 rc=pthread_create(&threads[t],NULL,(void *)PrintHello, (void *)&t); 28 if(rc!=0){ 29 printf("error. return code is %d\n", rc); 30 exit(-1); 31 } 32 // sleep(1); 33 // pthread_join(threads[t],NULL); 34 } 35 pthread_exit(NULL); 36 }
在這里主線程創建8個子線程,8個子線程都運行同一個函數PrintHello,休眠1s后打印傳入的參數為t
運行結果如下,主線程打印完8條"Creating thread"后經過1s左右子線程打印8條"Hello from thread"
如果取消掉32行或33行的注釋,則出現正確的結果:
那為什么會這樣呢?先貼一張圖
這是函數調用過程圖。沒錯,在對於整個進程來說,主線程生成子線程在由子線程執行某個函數,對CPU來說就是函數調用。從第一次的運行結果可以看出,其執行順序應該是先主線程執行到pthread_exit()然后等待所有的子線程運行,那這樣,有8次參數傳遞,而且都是存放在同一個地址,即調用者棧幀的ebp+8這個位置,而這個存放的是主線程即main函數棧幀中t的位置。所以,經過一次又一次的覆蓋,主線程執行完后最終傳遞給子線程的應該是最后一次變動后的t。