s threads podem gravar em diferentes elementos da mesma matriz de estruturas sem trava

Estou tentando usar threads (pela primeira vez!) Em um aplicativo GCC C que funciona bem no modo não-threaded. Quando o executo, alguns threads fornecem resultados que são todos zero, em vez das respostas necessárias (que eu sei para fins de verificação), mas os threads que dão zeros não são os mesmos sempre que o executo. As que dão respostas diferentes de zero estão corretas, então o código parece funcionar corretamente como tal. Gostaria de saber se alguém pode apontar áreas em que eu possa ter algo que não seja seguro para thread

Meus próprios pensamentos são que pode ser devido a como eu coleciono resultados ou talvez alocação de memória - eu uso malloc e free, mas em outro lugar no StackOverflow, vejo que o GCC malloc é considerado thread-safe se vinculado a -lpthread (o que estou fazendo). Nada usa variáveis globais / estáticas - tudo é passado como argumentos de funçã

Para passar os resultados de volta ao main, minha rotina encadeada usa uma matriz de estruturas. Cada encadeamento grava em um elemento distinto dessa matriz, portanto, eles não estão tentando gravar na mesma memória. Talvez eu precise usar alguma forma de bloqueio ao escrever resultados, mesmo que eles não atinjam o mesmo elemento da matriz da estrutura?

Eu segui a receita para o código encadeado aqui:https: //computing.llnl.gov/tutorials/pthreads/#Abstrac

Anexo extrações de código (simplificadas), caso isso dê alguma pista (posso ter omitido / modificado algo incorretamente, mas não estou pedindo a ninguém para detectar bugs, apenas a metodologia geral

typedef struct p_struct { /* used for communicating results back to main */
    int given[CELLS];
    int type;
    int status;
    /*... etc */
} puzstru;

typedef struct params_struct { /* used for calling generate function using threads */
    long seed;
    char *text;
    puzzle *puzzp;
    bool unique;
    int required;
} paramstru;
/* ========================================================================================== */
void *myfunc(void *spv) /* calling routine for use by threads */
{
    paramstru *sp=(paramstru *)spv;
    generate(sp->seed, sp->text, sp->puzzp, sp->unique, sp->required);
    pthread_exit((void*) spv);
}
/* ========================================================================================== */
int generate(long seed, char *text, puzstru *puzzp, bool unique, int required)
{
/* working code , also uses malloc and free,
    puts results in the element of a structure array pointed to by "puzzp", 
    which is different for each thread
    (see calling routine below :        params->puzzp=puz+thr; )
    extract as follows: */
            puzzp->given[ix]=calcgiven[ix];
            puzzp->type=1; 
            puzzp->status=1;
            /* ... etc */
}
/* ========================================================================================== */


int main(int argc, char* argv[])
{
    pthread_t thread[NUM_THREADS];
    pthread_attr_t threadattr;
    int thr,threadretcode;
    void *threadstatus;
    paramstru params[1];

    /* ....... ETC */

/* set up params structure for function calling parameters */
    params->text=mytext;
    params->unique=TRUE;
    params->required=1;

    /* Initialize and set thread detached attribute */
    pthread_attr_init(&threadattr);
    pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_JOINABLE);

    for(thr=0; thr<NUM_THREADS; thr++)
    {
        printf("Main: creating thread %d\n", thr);
        params->seed=ran_arr_next(startingseeds); 
        params->puzzp=puz+thr;
        threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)params); 
        if (threadretcode)
        {
            printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
            exit(-1);
        }
    }

    /* Free thread attribute and wait for the other threads */
    pthread_attr_destroy(&threadattr);
    for(thr=0; thr<NUM_THREADS; thr++)
    {
        threadretcode = pthread_join(thread[thr], &threadstatus);
        if (threadretcode)
        {
            printf("ERROR; return code from pthread_join() is %d\n", threadretcode);
            exit(-1);
        }
        printf("Main: completed join with thread %d having a status of %ld\n",thr,(long)threadstatus);
    }

/* non-threaded code, print results etc ............. */

    free(startingseeds);
    free(puz);
    printf("Main: program completed. Exiting.\n");
    pthread_exit(NULL);
}

Para benefício de outras pessoas que leem isso - todas as respostas estão corretas e a resposta à pergunta no cabeçalho é SIM, os threads podem escrever com segurança para diferentes elementos da mesma matriz de estruturas, meu problema estava na rotina de chamadas - o a seguir está o trecho de código alterado (agora funciona bem):

    paramstru params[NUM_THREADS];

    for(thr=0; thr<NUM_THREADS; thr++)
    {
        printf("Main: creating thread %d\n", thr);
    /* set up params structure for function calling parameters */
        params[thr].text=mytext;
        params[thr].unique=TRUE;
        params[thr].required=1;
        params[thr].seed=ran_arr_next(startingseeds); 
        params[thr].puzzp=puz+thr;
        threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)&params[thr]); 
        if (threadretcode)
        {
            printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
            exit(-1);
        }
    }

questionAnswers(3)

yourAnswerToTheQuestion