Кілька аргументів функції, викликаних pthread_create ()?


93

Мені потрібно передати кілька аргументів функції, яку я хотів би викликати в окремому потоці. Я читав, що типовим способом зробити це є визначення структури, передача функції вказівника на неї та розмежування її для аргументів. Однак я не можу змусити це працювати:

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

Результатом для цього має бути:

5
7

Але коли я запускаю його, я фактично отримую:

141921115
-1947974263

Хтось знає, що я роблю не так?


2
спробувати розподілити його на купі?
Карсон Майерс

1
@Carson Чому це має значення?
sigjuice

5
Ваша структура повинна жити принаймні стільки, скільки ваша нитка. Якщо ви створюєте потік і повертаєтесь із функції, яка називається pthread_create (), структура, виділена в стеці, може бути перезаписана іншими даними і може спричинити проблеми у вашій функції потоку. У цьому прикладі це не проблема, оскільки створюючий потік чекає завершення робочого потоку перед поверненням.
Комодор Ягер

@Commodore Jaeger О! Дякую, це проблема у мене була з тим, з ким я працював. Я виправив це, виділивши його в купі за допомогою malloc (), як сказав Карсон. Зараз це має набагато більше сенсу.
Майкл

Відповіді:


77

Тому що ти кажеш

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

замість

struct arg_struct *args = arguments;


5
@sigjuice, у мене це не працює. Я бачу помилку компіляції: недійсне перетворення з 'void *' в 'arg_struct *'.
Нешта

20

використання

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

замість

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

4

main()має власні змінні потоку та стека. або виділити пам'ять для 'args' у купі, або зробити її глобальною:

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

//declares args as global out of main()

Тоді, звичайно, змініть посилання args->arg1на args.arg1тощо.


2

Використання:

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

І передайте ці аргументи так:

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

Не забувайте про безкоштовні сварки! ;)


1

Аргументи print_the_arguments - це аргументи, тому слід використовувати:

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

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

-> це призначення неправильне, я маю на увазі аргумент змінної, який слід використовувати в цьому контексті. На ура !!!


1

При створенні потоку цього коду передається адреса вказівника на функцію. Оригінальний pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Це повинно читатись як pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Хороший спосіб пам’ятати, що всі аргументи цієї функції повинні бути адресами.

some_threadоголошується статично, тому адреса надсилається належним чином із використанням &.

Я створив би pthread_attr_tзмінну, а потім використав би pthread_attr_init()її та передав адресу цієї змінної. Але передача NULLвказівника також є допустимою.

&У передній частині етикетки функції є те , що викликає питання тут. Етикетка вже використовуєтьсяvoid* функцією, тому необхідна лише мітка.

Сказати != 0з останнім аргументом, здається, спричиняє невизначену поведінку. Додавання цього означає, що замість посилання передається логічне значення.

Відповідь Akash Agrawal також є частиною вирішення проблеми цього коду.


1

У мене таке саме питання, як у оригінального плаката, Майкл.

Однак я намагався застосувати відповіді, подані для оригінального коду, безуспішно

Після деяких спроб і помилок, ось моя версія коду, який працює (або принаймні працює для мене!). І якщо ви уважно придивитесь, то помітите, що це відрізняється від попередніх опублікованих рішень.

#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 */
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.