Pthread_create () tarafından çağrılan işlev için birden çok argüman var mı?


96

Ayrı bir iş parçacığında çağırmak istediğim bir işleve birden çok argüman iletmem gerekiyor. Ya sahibim yapmanın tipik yolunun bir yapı tanımlamak, işleve buna bir işaretçi geçirmek ve argümanlar için ondan referans almak olduğunu okudum . Ancak, bunu çalıştıramıyorum:

#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 */
}

Bunun çıktısı şöyle olmalıdır:

5
7

Ama çalıştırdığımda aslında şunu elde ederim:

141921115
-1947974263

Neyi yanlış yaptığımı bilen var mı?


2
yığın üzerinde ayırmayı denemek?
Carson Myers

1
@Carson Bu neden bir fark yaratsın?
sigjuice

5
Yapınız en az ipliğiniz kadar uzun yaşamalıdır. Bir evre oluşturuyorsanız ve pthread_create () adlı işlevden dönüyorsanız, yığın üzerinde ayrılan yapı diğer veriler tarafından üzerine yazılabilir ve evre işlevinizde sorunlara neden olabilir. Bu örnekte, yaratılan iş parçacığı geri dönmeden önce çalışan iş parçacığının tamamlanmasını beklediği için bu bir sorun değildir.
Commodore Jaeger

@Commodore Jaeger Oh! Teşekkür ederim, birlikte çalıştığım diğer kişiyle yaşadığım sorun buydu. Carson'un dediği gibi malloc () kullanarak öbek üzerine ayırarak düzelttim. Bu şimdi çok daha mantıklı.
Michael

Yanıtlar:


78

Çünkü sen diyorsun

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

onun yerine

struct arg_struct *args = arguments;


5
@sigjuice, Benim için çalışmıyor. Derleme hatası görüyorum: 'void *' den 'arg_struct *' a geçersiz dönüşüm.
Neshta

20

kullanım

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

yerine

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

4

main()kendi iş parçacığı ve yığın değişkenlerine sahiptir. ya yığındaki 'args' için bellek ayırın ya da onu global yapın:

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

//declares args as global out of main()

Sonra elbette referansları ' args->arg1den args.arg1vb. Olarak değiştirin .


2

Kullanım:

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

Ve bu argümanları şu şekilde iletin:

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

Ücretsiz argümanları unutma! ;)


1

Print_the_arguments değişkenleri argümanlardır, bu yüzden şunu kullanmalısınız:

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

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

-> bu atama yanlış, yani değişken argümanı bu bağlamda kullanılmalı. Şerefe !!!


1

Bu kodun evre yaratımında, bir fonksiyon göstericisinin adresi geçmektedir. Orijinal pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Olarak okunmalı pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Hatırlamanın iyi bir yolu, bu işlevin tüm argümanlarının adresler olması gerektiğidir.

some_thread statik olarak bildirilir, bu nedenle adres, & .

Bir pthread_attr_tdeğişken yaratır , sonra kullanır pthread_attr_init()ve bu değişkenin adresini iletirim. Ancak, bir NULLişaretçi geçmek de geçerlidir.

&Fonksiyon etiketin ön burada soruna neden olan budur. Kullanılan etiket zaten bir void*işlevdir, bu nedenle yalnızca etiket gereklidir.

!= 0Son argümanla söylemek , belirsiz davranışlara neden olur. Bunun eklenmesi, bir referans yerine bir boole'nin geçirildiği anlamına gelir.

Akash Agrawal'ın yanıtı da bu kodun sorununun çözümünün bir parçasıdır.


1

Orijinal afişle aynı sorum var, Michael.

Ancak orijinal kod için verilen cevapları başarılı bir şekilde uygulamaya çalıştım

Bazı deneme yanılmalardan sonra, işte çalışan (veya en azından benim için çalışan!) Kod sürümüm. Ve yakından bakarsanız, yayınlanan önceki çözümlerden farklı olduğunu fark edeceksiniz.

#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 */
}

0

Yana C ++ aynı soruyu soran ama bir yinelenen kabul edilir Ben de cevap olarak C ++ kodu tedarik olabilir.

//  hello-2args.cpp
// /programming/1352749
#include <iostream>
#include <omp.h>
#include <pthread.h>
using namespace std;

typedef struct thread_arguments {
  int thrnr;
  char *msg;
} thargs_t;

void *print_hello(void *thrgs) {
  cout << ((thargs_t*)thrgs)->msg << ((thargs_t*)thrgs)->thrnr << "\n";
  pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
  cout << " Hello C++!\n";
  const int NR_THRDS = omp_get_max_threads();
  pthread_t threads[NR_THRDS];
  thargs_t thrgs[NR_THRDS];
  for(int t=0;t<NR_THRDS;t++) {
    thrgs[t].thrnr = t;
    thrgs[t].msg = (char*)"Hello World. - It's me! ... thread #";
    cout << "In main: creating thread " << t << "\n";
    pthread_create(&threads[t], NULL, print_hello, &thrgs[t]);
  }
  for(int t=0;t<NR_THRDS;t++) {
    pthread_join(threads[t], NULL);
  }
  cout << "After join: I am always last. Byebye!\n";
  return EXIT_SUCCESS;
}

Aşağıdakilerden birini kullanarak derleyin ve çalıştırın:

g++ -fopenmp -pthread hello-2args.cpp && ./a.out # Linux
g++ -fopenmp -pthread hello-2args.cpp && ./a.exe # MSYS2, Windows
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.