pthread с уникальной структурой в качестве параметра C - PullRequest
1 голос
/ 05 апреля 2010

У меня есть этот кусок кода, который доставляет мне неприятности. Я знаю, что все темы читают одну и ту же структуру. Но я понятия не имею, как это исправить.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int a,b;
} s_param;

void *
threadfunc(void *parm)
{
  s_param *param2 = parm; 
  printf("ID:%d and v:%d\n",param2->a,param2->b);
  pthread_exit(NULL);
}

int main(int argc, char **argv)
{
  pthread_t thread[3];
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    s_param param;
    param.b=10;
    param.a=i;
    rc = pthread_create(&thread[i], NULL, threadfunc, &param ); // !!!!
    if(rc){
      exit(1);
    }
  }  

  for(i=0; i<3 ; ++i){
    pthread_join(thread[i],&status);
  }
  return 0;
}

выход:

ID:2 and v:10
ID:2 and v:10
ID:2 and v:10

и что мне нужно:

ID:0 and v:10
ID:1 and v:10
ID:2 and v:10

Ответы [ 3 ]

5 голосов
/ 05 апреля 2010

Область действия sparam в цикле for является статической в ​​этом цикле. Когда вы устанавливаете .a и .b, вы снова и снова пишете в одну и ту же структуру, и все три потока получают указатель на одну и ту же структуру.

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

int main(int argc, char **argv)
{
  pthread_t thread[3];
  s_param param[3];
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    param[i].b=10;
    param[i].a=i;
    rc = pthread_create(&thread[i], NULL, threadfunc, &param[i] ); // !!!!
    if(rc){
      exit(1);
    }
  } 
... etc

Следует отметить, что создание структур (и потоков) в массиве, подобном этому, возможно только потому, что вы явно выполняете join () с основным потоком. Если вы не сделали этого объединения, вам бы посоветовали либо статически распределить структуры вне основной функции, либо распределить их по малой части из кучи, потому что, как только поток ввода выходит из основной функции, кадр стека, содержащий массив станет недействительным и вскоре будет перезаписан непредсказуемым образом.

2 голосов
/ 05 апреля 2010

param является локальной переменной. Это выходит из области видимости в конце скобок цикла. Вам нужно malloc новый s_param с каждой нитью.

Или лучше определить структуру, содержащую pthread_t и s_param, и использовать этот тип для thread[3].

typedef struct {
  int a,b;
  pthread_t t;
} s_param;

int main(int argc, char **argv)
{
  s_param thread[3]; // declare threads + params together
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    s_param *param = &thread[i]; // no persistent data declared here
    param->b=10;
    param->a=i;
    rc = pthread_create(&thread[i].t, NULL, threadfunc, &thread[i] ); // !!!!
    if(rc){
      exit(1);
    }
  }  
…
2 голосов
/ 05 апреля 2010

param живет на том же месте в стеке во время выполнения вашей функции main. Каждый раз, когда вы устанавливаете новые значения, они стирают старые значения, и все threadfunc смотрят на одно и то же место в памяти. malloc структуры, или иным образом создавать их из разных мест памяти. (Кроме того, использование стековой памяти для многопоточных структур данных вызывает беспокойство; как только функция, для которой вы устанавливаете их, выходит, память становится недействительной.)

...