Beberapa argumen ke fungsi dipanggil oleh pthread_create ()?

96

Saya perlu meneruskan beberapa argumen ke fungsi yang ingin saya panggil di utas terpisah. Saya telah membaca bahwa cara khas untuk melakukan ini adalah dengan mendefinisikan sebuah struct, meneruskan fungsi sebuah pointer ke sana, dan membedakannya untuk argumen. Namun, saya tidak dapat membuat ini berfungsi:

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

struct arg_struct {
    int arg1;
    int arg2;
};

void *print_the_arguments(void *arguments)
{
    struct arg_struct *args = (struct arg_struct *)args;
    printf("%d\n", args -> arg1);
    printf("%d\n", args -> arg2);
    pthread_exit(NULL);
    return NULL;
}

int main()
{
    pthread_t some_thread;
    struct arg_struct args;
    args.arg1 = 5;
    args.arg2 = 7;

    if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
        printf("Uh-oh!\n");
        return -1;
    }

    return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

Output untuk ini seharusnya:

5
7

Tetapi ketika saya menjalankannya, saya benar-benar mendapatkan:

141921115
-1947974263

Ada yang tahu apa yang saya lakukan salah?

Michael
sumber
2
coba alokasikan di heap?
Carson Myers
1
@Carson Mengapa hal itu membuat perbedaan?
sigjuice
5
Struktur Anda harus hidup setidaknya selama utas Anda. Jika Anda membuat utas dan kembali dari fungsi yang disebut pthread_create (), struktur yang dialokasikan di tumpukan mungkin ditimpa oleh data lain dan dapat menyebabkan masalah dalam fungsi utas Anda. Dalam contoh ini, itu bukan masalah, karena utas pembuatan menunggu utas pekerja selesai sebelum kembali.
Commodore Jaeger
@Codore Jaer Oh! Terima kasih, itulah masalah yang saya alami dengan orang lain yang saya tangani. Saya memperbaikinya dengan mengalokasikannya di heap menggunakan malloc (), seperti yang dikatakan Carson. Itu jauh lebih masuk akal sekarang.
Michael

Jawaban:

78

Karena kamu bilang

struct arg_struct *args = (struct arg_struct *)args;

dari pada

struct arg_struct *args = arguments;

sigjuice.dll
sumber
5
@sigjuice, Ini tidak berhasil untuk saya. Saya melihat kesalahan kompilasi: konversi tidak valid dari 'void *' menjadi 'arg_struct *'.
Neshta
20

menggunakan

struct arg_struct *args = (struct arg_struct *)arguments;

di tempat

struct arg_struct *args = (struct arg_struct *)args;
Akash Agrawal
sumber
4

main()memiliki variabel utas dan tumpukannya sendiri. mengalokasikan memori untuk 'args' di heap atau menjadikannya global:

struct arg_struct {
    int arg1;
    int arg2;
}args;

//declares args as global out of main()

Kemudian tentu saja mengubah referensi dari args->arg1ke args.arg1dll ..

Plamen Panov
sumber
2

Menggunakan:

struct arg_struct *args = malloc(sizeof(struct arg_struct));

Dan berikan argumen ini seperti ini:

pthread_create(&tr, NULL, print_the_arguments, (void *)args);

Jangan lupakan argumen gratis! ;)

Elham
sumber
1

Argumen print_the_arguments adalah argumen, jadi Anda harus menggunakan:

struct arg_struct *args = (struct arg_struct *)arguments. 
Batu Karton
sumber
1
struct arg_struct *args = (struct arg_struct *)args;

-> tugas ini salah, maksud saya argumen variabel harus digunakan dalam konteks ini. Bersulang!!!

Jashmikant
sumber
1

Dalam pembuatan utas kode ini, alamat penunjuk fungsi sedang diteruskan. Asli pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Ini harus dibaca sebagai pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Cara yang baik untuk mengingat adalah bahwa semua argumen fungsi ini harus berupa alamat.

some_threaddideklarasikan secara statis, sehingga alamat dikirim dengan benar menggunakan &.

Saya akan membuat pthread_attr_tvariabel, lalu menggunakannya pthread_attr_init()dan meneruskan alamat variabel itu. Tapi, melewatkan NULLpointer juga valid.

Bagian &depan label fungsi inilah yang menyebabkan masalah di sini. Label yang digunakan sudah menjadi void*suatu fungsi, jadi hanya label yang diperlukan.

Mengatakan != 0dengan argumen terakhir tampaknya akan menyebabkan perilaku yang tidak dapat ditentukan. Menambahkan ini berarti bahwa boolean sedang diteruskan, bukan referensi.

Jawaban Akash Agrawal juga merupakan bagian dari solusi untuk masalah kode ini.

Rayshaun Preston
sumber
1

Saya memiliki pertanyaan yang sama dengan poster asli, Michael.

Namun saya telah mencoba menerapkan jawaban yang dikirimkan untuk kode asli tanpa hasil

Setelah beberapa kali coba-coba, berikut adalah versi kode saya yang berfungsi (atau setidaknya berfungsi untuk saya!). Dan jika Anda melihat lebih dekat, Anda akan melihat bahwa ini berbeda dengan solusi sebelumnya yang diposting.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct arg_struct
{
   int arg1;
   int arg2;
} *args;

void *print_the_arguments(void *arguments)
{
   struct arg_struct *args = arguments;
   printf("Thread\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   pthread_exit(NULL);
   return NULL;
}

int main()
{
   pthread_t some_thread;
   args = malloc(sizeof(struct arg_struct) * 1);

   args->arg1 = 5;
   args->arg2 = 7;

   printf("Before\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   printf("\n");


   if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
   {
      printf("Uh-oh!\n");
      return -1;
   }

   return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
VeeDub
sumber