Nhiều đối số cho hàm được gọi bởi pthread_create ()?


94

Tôi cần truyền nhiều đối số cho một hàm mà tôi muốn gọi trên một chuỗi riêng. Tôi đã đọc rằng cách điển hình để làm điều này là xác định một cấu trúc, chuyển hàm một con trỏ đến đó và tham chiếu nó cho các đối số. Tuy nhiên, tôi không thể làm cho điều này hoạt động:

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

Đầu ra cho điều này phải là:

5
7

Nhưng khi tôi chạy nó, tôi thực sự nhận được:

141921115
-1947974263

Có ai biết tôi đang làm gì sai không?


2
thử phân bổ nó trên heap?
Carson Myers

1
@Carson Tại sao điều đó nên tạo ra sự khác biệt?
sigjuice

5
Cấu trúc của bạn ít nhất phải tồn tại lâu dài như chủ đề của bạn. Nếu bạn đang tạo một luồng và quay lại từ hàm có tên pthread_create (), cấu trúc được phân bổ trên ngăn xếp có thể bị ghi đè bởi dữ liệu khác và có thể gây ra sự cố trong hàm luồng của bạn. Trong ví dụ này, đó không phải là vấn đề, vì luồng tạo sẽ đợi luồng công nhân hoàn thành trước khi quay trở lại.
Commodore Jaeger

@Coodore Jaeger Ôi! Cảm ơn bạn, đó là vấn đề tôi đang gặp phải với người khác mà tôi đang làm việc cùng. Tôi đã sửa nó bằng cách phân bổ nó trên heap bằng cách sử dụng malloc (), như Carson đã nói. Điều đó có ý nghĩa hơn bây giờ.
Michael

Câu trả lời:


77

Bởi vì bạn nói

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

thay vì

struct arg_struct *args = arguments;


5
@sigjuice, Nó không hiệu quả với tôi. Tôi thấy lỗi biên dịch: chuyển đổi không hợp lệ từ 'void *' thành 'arg_struct *'.
Neshta

20

sử dụng

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

thay cho

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

4

main()có các biến luồng và biến ngăn xếp của riêng nó. phân bổ bộ nhớ cho 'args' trong heap hoặc làm cho nó toàn cục:

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

//declares args as global out of main()

Sau đó, tất nhiên thay đổi các tham chiếu từ args->arg1thành args.arg1vv.


2

Sử dụng:

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

Và chuyển các đối số như thế này:

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

Đừng quên args miễn phí! ;)


1

Các args của print_the_arguments là các đối số, vì vậy bạn nên sử dụng:

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

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

-> việc gán này là sai, ý tôi là đối số biến nên được sử dụng trong ngữ cảnh này. Chúc mừng !!!


1

Trong quá trình tạo luồng của mã này, địa chỉ của một con trỏ hàm đang được chuyển. Bản gốc pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Nó sẽ đọc là pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Một cách tốt để nhớ là tất cả các đối số của hàm này phải là địa chỉ.

some_threadđược khai báo tĩnh, vì vậy địa chỉ được gửi đúng cách &.

Tôi sẽ tạo một pthread_attr_tbiến, sau đó sử dụng pthread_attr_init()nó và chuyển địa chỉ của biến đó. Tuy nhiên, việc chuyển một NULLcon trỏ cũng hợp lệ.

Phía &trước nhãn chức năng là nguyên nhân gây ra sự cố ở đây. Nhãn được sử dụng đã là void*một hàm, vì vậy chỉ nhãn là cần thiết.

Để nói != 0với lý lẽ cuối cùng dường như sẽ gây ra hành vi không xác định. Thêm điều này có nghĩa là một boolean đang được chuyển thay vì một tham chiếu.

Câu trả lời của Akash Agrawal cũng là một phần của giải pháp cho vấn đề của mã này.


1

Tôi có câu hỏi giống như người đăng ban đầu, Michael.

Tuy nhiên, tôi đã thử áp dụng các câu trả lời được gửi cho mã gốc mà không thành công

Sau một số thử nghiệm và lỗi, đây là phiên bản mã của tôi hoạt động (hoặc ít nhất là phù hợp với tôi!). Và nếu bạn quan sát kỹ, bạn sẽ nhận thấy rằng nó khác với các giải pháp được đăng trước đó.

#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 */
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.