Передача структур в качестве аргументов при использовании pthread_create()

StackOverflow https://stackoverflow.com/questions/863952

Вопрос

Я попытался передать структуру в качестве четвертого аргумента при использовании pthread_create() с чем-то вроде этого:

pthread_create(&tid1, NULL, calca, &t); //t is the struct

Теперь всякий раз, когда я пытаюсь получить доступ к переменным в структуре - t.a, t.b или t.c, я продолжаю получать сообщение об ошибке - запрос на членство в чем-то, а не в структуре или объединении.

Какой альтернативный метод я могу использовать для передачи структур в поток?

Это было полезно?

Решение

Вероятно, вы создаете структуру в той же области, что и pthread_create.Эта структура перестанет быть действительной после выхода из этой области.

Попробуйте создать указатель на структуру в куче и передать этот указатель структуры в свой поток.Не забудьте удалить где-нибудь эту память (в теме, если вы никогда больше не будете ее использовать или когда она вам больше не понадобится).

Кроме того, как упоминал Киберконте, если вы собираетесь получать доступ к этим данным из разных потоков, вам необходимо заблокировать доступ к ним с помощью мьютекса или критической секции.

Редактировать: 14 мая 2009 г., 12:19 по восточному стандартному времени.:Кроме того, как уже отмечали другие люди, вам необходимо привести параметр к правильному типу.

Если вы передаете переменную, которая является глобальной структурой (на чем вы, похоже, настаиваете), ваша функция потока должна будет привести к типу:

void my_thread_func(void* arg){
    my_struct foo = *((my_struct*)(arg)); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}

Или, если вы передаете указатель на свою структуру:

void my_thread_func(void* arg){
    my_struct* foo = (my_struct*)arg; /* Cast the void* to our struct type */
    /* Access foo->a, foo->b, foo->c, etc. here */
}

Другие советы

Если вы находитесь внутри функции потока, передаваемый вами аргумент является void*.Вам нужно будет привести его к структуре, прежде чем вы сможете использовать его как таковой.

void my_thread_func(void* arg){
    my_struct foo = (my_struct)(*arg); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}
  1. Создать семафор

  2. Создайте еще одну структуру, состоящую из указателя на вашу структуру и дескриптора семафора.

  3. Передайте указатель на эту новую структуру в pthread_create.

  4. В родительском потоке, т.е.это называется pthread_create, дождитесь семафора

  5. В дочернем потоке скопируйте элементы вашей структуры в локальные переменные или сохраните их в другом месте.

  6. В дочернем потоке подайте сигнал семафору

  7. В родительском потоке закройте семафор

Вы можете использовать общую память или глобальную переменную (если этот аргумент больше не понадобится) или связанный список, если это потоки, которые получают данные.

Просто не забудьте заблокировать переменные, которые используются совместно потоками.

Однако без фактического кода-нарушителя я не могу сказать вам, что вы делаете неправильно в своей текущей реализации.

Это сообщение об ошибке означает, что вы не разыменовываете указатель.

Ты говоришь "т.а" вместо "т->а"

[me@myhost ~]$ cat testitx.c
struct x {
        int a, b;
};

int main(int argc, char *argv[])
{
        struct x y, *z;

        z = &y;
        z.a = 10;
}
[me@myhost ~]$ cc -c testitx.c
testitx.c: In function `main':
testitx.c:10: error: request for member `a' in something not a structure or union
[me@myhost ~]$

Раньше я часто допускал те же ошибки, которые перечислены в других ответах, но теперь я использую немного другой подход, который переносит потенциальную ошибку из функции потоковой передачи на вызов pthread_create.

Я объявляю и определяю функцию потоковой передачи «обычным» способом:

void *ThreadFunction(sPARAMETERS *Params) {

  // do my threading stuff...

}

и когда я вызываю pthread_create, мне нужно использовать приведение:

pthread_create(&ThreadId,0,(void*(*)(void*)) &ThreadFunction,&Params);

Я почти никогда не забываю использовать & в параметрах, и компилятор позаботится о любых ошибках, которые я допускаю на другом конце.Отлично работает и для обратных вызовов.

my_struct foo = (my_struct)(*arg);ISECEECT попробуйте my_struct *foo = (my_struct *) (arg);
И, int, функция, вызывающая поток, убедитесь, что ее статическая (так что память, на которую указывается, не теряется в тумане)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top