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

17

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

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

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

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

    
задан skinderneath 14.05.2009 в 17:15
источник

7 ответов

24

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

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

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

Редактировать Май 14th, 2009 @ 12:19 PM EST : Кроме того, как говорили другие люди, вам нужно указать свой параметр на правильный тип.

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

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 */
}
    
ответ дан Lyndsey Ferguson 14.05.2009 в 17:27
  • Фактически, я создал поток в основной функции и создал структуру сразу после включения файлов заголовков. Поэтому он должен быть доступен всеми функциями (исправьте меня, если я ошибаюсь). –  skinderneath 14.05.2009 в 18:19
  • Ваше последнее редактирование было самым полезным для вас до сих пор. Благодарю. –  skinderneath 14.05.2009 в 18:31
  • Спасибо, это спасло мой бекон. –  g33kz0r 14.03.2013 в 20:15
2

Если вы находитесь внутри вашей функции потока, аргумент, который вы передаете, является 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 */
}
    
ответ дан Harper Shelby 14.05.2009 в 17:22
  • Я сделал это, но теперь я получаю ошибку «разыменования» void * 'pointer ". –  skinderneath 14.05.2009 в 17:56
  • Харпер хотел написать: my_struct foo = * (my_struct *) arg; или my_struct * foo = (my_struct *) arg; –  Jonathan Leffler 14.05.2009 в 18:32
  • Используется эта идея и опубликовано редактирование Lyndsey Ferguson - 14 мая 2009 года, 12:19 вечера EST. –  skinderneath 14.05.2009 в 18:33
  • Да, c-style casts не моя сильная сторона, и прошло несколько лет с тех пор, как я использовал pthread_create. Я предпочитаю C ++ и хорошую библиотеку потоков. –  Harper Shelby 14.05.2009 в 20:23
1
  1. Создать семафор

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

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

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

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

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

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

ответ дан dmityugov 15.05.2009 в 11:50
0

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

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

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

    
ответ дан cyberconte 14.05.2009 в 17:21
  • Удалено проголосовало из-за расширения ответа. –  Harper Shelby 14.05.2009 в 17:25
0

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

Вы говорите «t.a» вместо «t- & gt; a»

[[email protected] ~]$ cat testitx.c
struct x {
        int a, b;
};

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

        z = &y;
        z.a = 10;
}
[[email protected] ~]$ cc -c testitx.c
testitx.c: In function 'main':
testitx.c:10: error: request for member 'a' in something not a structure or union
[[email protected] ~]$
    
ответ дан smcameron 14.05.2009 в 17:34
  • Не помогает. Я использовал решение Харпера Шелби, чтобы получить ошибку «разыменования» void * 'pointer. –  skinderneath 14.05.2009 в 18:17
0

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

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

void *ThreadFunction(sPARAMETERS *Params) {

  // do my threading stuff...

}

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

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

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

    
ответ дан Marc Bernier 14.05.2009 в 17:55
  • С технической точки зрения, это неопределенное поведение - хотя на большинстве компиляторов он будет работать для обычных указателей структуры. Не пытайтесь с помощью указателей на функции C ++ ... –  bdonlan 14.05.2009 в 18:01
  • Я не понимаю, как это помогает решить мою проблему. Те приведения, которые вы использовали, слишком загадочны. –  skinderneath 14.05.2009 в 18:20
0

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

    
ответ дан user3512266 25.07.2014 в 20:32