簡體   English   中英

pthread_exit的退出值錯誤

[英]Wrong exit value from pthread_exit

下面的代碼僅創建兩個線程並嘗試獲取它們的返回值。

我已經編譯並在32位glibc-2.15系統上運行它,一切正常(輸出:r1:1,r2:2)。 但是,當我在64位glibc-2.17系統上執行相同操作時,輸出錯誤(輸出:r1:0,r2:2)。 為什么相同的代碼在不同的系統上表現不同?

注意:如果將r1和r2的類型更改為void*int* (如下所述),則代碼在兩個系統上均適用。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>

void* worker(void* arg) {
    int i = (int) arg;
    pthread_exit((void*)i);
}

int main(int argc, char** argv) {

    pthread_t tid[2];
    int err = 0;
    err = pthread_create(&tid[0], NULL, worker, (void*) 1);
    if(err != 0) printf("error: %s\n", strerror(err));
    err = pthread_create(&tid[1], NULL, worker, (void*) 2);
    if(err != 0) printf("error: %s\n", strerror(err));

    ///*
    int r1 = 0, r2 = 0; // <-- WRONG: r1: 0, r2: 2
    //void *r1, *r2; // <-- OK: r1: 1, r2: 2
    pthread_join(tid[0], (void**) &r1);
    pthread_join(tid[1], (void**) &r2);
    printf("r1: %d, r2: %d\n", (int) r1, (int) r2);
    //*/

    // make comment above snippet and uncomment below snippet: // <-- OK: r1: 1, r2: 2 
    /*
    int *r1 = (int*) malloc(sizeof(int));
    int *r2 = (int*) malloc(sizeof(int));
    pthread_join(tid[0], (void**) r1);
    pthread_join(tid[1], (void**) r2);
    printf("r1: %d, r2: %d\n", (int)(*r1), (int)(*r2));
    */
    return 0;
}

簡短的答案:在64位系統上, sizeof(void*) != sizeof(int) ,並且通過將&int傳遞給pthread_join您正在調用未定義的行為(並破壞了堆棧;在Address Sanitizer下運行該程序的變體應該可以檢測到錯誤)。

在傳遞&int ,但int是堆分配的情況下,您正在破壞堆,但是您尚未注意到(您的程序稍后可能在隨后的mallocfree上崩潰)。 在Valgrind或Address Sanitizer下運行該程序的變體應該可以向您證明堆損壞。

更長的答案: pthread_join(tid, &x)本質上執行此操作:

memcpy(&x, previosly_used_pthread_exit_value, sizeof(void*));

現在應該很清楚,傳入sizeof(x) < sizeof(void*)的任何變量的地址都會調用未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM