# **Pthread return value 探討** 根據"並行和多執行緒程式設計課程"裡的 POSIX Thread 章節 https://hackmd.io/@sysprog/concurrency/%2F%40sysprog%2Fposix-threads 其中程式碼: ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> void printMsg(char *msg) { int *status_c = malloc(sizeof(int)); *status_c = 1; printf("%s\n", msg); pthread_exit(status_c); } int main(int argc, char **argv) { pthread_t thrdID; int *status_p = malloc(sizeof(int)); printf("creating a new thread\n"); pthread_create(&thrdID, NULL, (void *) printMsg, argv[1]); printf("created thread %lu\n", thrdID); pthread_join(thrdID, (void**) &status_p); printf("Thread %lu exited with status %d\n", thrdID, *status_p); return 0; } ``` 方便起見, 我們修改變數名稱為 status_c 和 status_p 分別代表child/parent 宣告的return value pointer 其中main 裡面的宣告接收thread return value的參數 ``` int *status_p = malloc(sizeof(int)); ``` 真的需要額外再malloc 一個空間嗎? ``` pthread_join(thrdID, (void**) &status_p); ``` 究竟是把thread status_c 複製一份到 status_p 還是 讓status_p 指向status_c? 可觀察pthread_join 定義 ``` int pthread_join(pthread_t thread, void **retval); ``` retval 為pointer of pointer, 合理推測其行為應是"讓status_p 指向status_c" # **gdb 驗證:** ``` chandler@lima-default:~/Embedded_Class/week3/pthread$ gdb -q --args pthread "Hello" Reading symbols from pthread... (gdb) l 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 5 void printMsg(char *msg) 6 { 7 int *status_c = malloc(sizeof(int)); 8 *status_c = 1; 9 printf("%s\n", msg); 10 pthread_exit(status_c); (gdb) l 11 } 12 13 int main(int argc, char **argv) 14 { 15 pthread_t thrdID; 16 int *status_p = malloc(sizeof(int)); 17 18 printf("creating a new thread\n"); 19 pthread_create(&thrdID, NULL, (void *) printMsg, argv[1]); 20 printf("created thread %lu\n", thrdID); (gdb) l 21 pthread_join(thrdID, (void**) &status_p); 22 printf("Thread %lu exited with status %d\n", thrdID, *status_p); 23 24 return 0; 25 } Breakpoint 2, main (argc=2, argv=0xfffffffff258) at pthread.c:18 18 printf("creating a new thread\n"); (gdb) p status_p $1 = (int *) 0xaaaaaaac12a0 (gdb) c Continuing. creating a new thread [New Thread 0xfffff7dff1a0 (LWP 35473)] created thread 281474840392096 [Switching to Thread 0xfffff7dff1a0 (LWP 35473)] Thread 2 "pthread" hit Breakpoint 1, printMsg (msg=0xfffffffff52e "Hello") at pthread.c:8 8 *status_c = 1; (gdb) p status_c $2 = (int *) 0xfffff0000b70 (gdb) c Continuing. Hello [Thread 0xfffff7dff1a0 (LWP 35473) exited] [Switching to Thread 0xfffff7ff7ee0 (LWP 35470)] Thread 1 "pthread" hit Breakpoint 3, main (argc=2, argv=0xfffffffff258) at pthread.c:22 22 printf("Thread %lu exited with status %d\n", thrdID, *status_p); (gdb) p status_p $3 = (int *) 0xfffff0000b70 ``` 可觀察確實為修改指標 # 檢視glibc 裡的source code https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_join.c;h=6a87a8b329c3e34a57d65e86d45fa97a5fdb2fe2;hb=HEAD ``` 99 if (__builtin_expect (result == 0, 1)) 100 { 101 /* We mark the thread as terminated and as joined. */ 102 pd->tid = -1; 103 104 /* Store the return value if the caller is interested. */ 105 if (thread_return != NULL) 106 *thread_return = pd->result; 107 108 109 /* Free the TCB. */ 110 __free_tcb (pd); 111 } 112 ``` 確實也是修改指標, 並沒有做memory copy 的動作 # 結論 main 裡的status_p 不應使用malloc 程式碼應改寫為 ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> void printMsg(char *msg) { int *status_c = malloc(sizeof(int)); *status_c = 1; printf("%s\n", msg); pthread_exit(status_c); } int main(int argc, char **argv) { pthread_t thrdID; int *status_p; printf("creating a new thread\n"); pthread_create(&thrdID, NULL, (void *) printMsg, argv[1]); printf("created thread %lu\n", thrdID); pthread_join(thrdID, (void**) &status_p); printf("Thread %lu exited with status %d\n", thrdID, *status_p); return 0; } ```