# **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;
}
```