2009-11-06 6 views
1

Le code suivant génère une sortie incorrecte et incohérente avec gcc (4.1.2 20080704) mais une sortie correcte et attendue avec icc (version 11.1). Mais quand j'ai déplacé la définition de thread_data_array [] de main() à global (immédiatement après la définition de struct thread_data) cela fonctionne bien avec les deux compilateurs. Je ne vois pas pourquoi ce changement devrait faire la différence. Je voudrais générer des threads de façon récursive, donc je dois l'appeler à partir d'une fonction mais pas définir comme global. Quelqu'un pourrait-il expliquer ce qui ne va pas le code s'il vous plaît?pthreads: incohérence entre gcc et icc sous Linux

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

#define NUM_THREADS 4 

struct thread_data { 
    int thread_id; 
    int sum; 
}; 

/* struct thread_data thread_data_array[NUM_THREADS]; */ 

void *p_task(void *threadarg) 
{ 
    struct thread_data *my_data; 
    int taskid; 
    int sum; 

    my_data = (struct thread_data *) threadarg; 
    taskid = my_data->thread_id; 
    sum = my_data->sum; 

    printf("Thread #%d with sum %d\n", taskid, sum); 

    for (sum = 0; sum < 000000000; sum++) { 
     for (taskid = 0; taskid < 000000000; taskid++) { 
      sum+=taskid; 
     } 
    } 

    return my_data; 
} 

int main() 
{ 
    struct thread_data thread_data_array[NUM_THREADS]; /*this does not work*/ 

    pthread_t threads[NUM_THREADS]; 
    int rc; 
    long t; 

    for (t = 0; t < NUM_THREADS; t++) { 
     thread_data_array[t].thread_id = t; 
     thread_data_array[t].sum = (int) t*2; 
     rc = pthread_create(&threads[t], NULL, p_task, (void *) &thread_data_array[t]); 
    } 

    pthread_exit(NULL); 

    return 0; 

} 
+0

Le 'problème' n'est pas observé avec la version 4.4.1 de gcc. Cela pourrait-il être un bug dans GCC? Le plus ancien était le dernier de CentOS, donc je me demande ... – user203405

+0

Juste comme un point mineur, toutes les questions devraient avoir une section «c'est ce que j'attends» et une section «c'est ce qui se passe réellement» :-) – paxdiablo

+0

Je l'ai, sire. : D – user203405

Répondre

5

Eh bien, ma première pensée serait que le thread principal est en fait sortir, et en prenant son cadre de pile avec elle, avant que les autres fils sont terminés. De ce que je me souviens de pthreads (et il y a plus d'une décennie et demie, en les utilisant avec DCE), il n'y a absolument rien de spécial sur le thread principal autre que la taille de la pile.

Si le tableau est déclaré global, la sortie de main aura aucun effet sur elle, mais, si elle est dans le cadre de la pile pour main, je serais très prudent de l'utiliser après sa sortie. Je base cette partie sur des conjectures puisque vous n'avez pas réellement expliqué ce que le comportement est que vous voyez.

Je suggère d'insérer le code suivant avant le pthread_exit dans main:

for (t = 0; t < NUM_THREADS; t++) 
    pthread_join (threads[t], NULL); 
+0

Merci. "(void) pthread_join (threads [t], NULL);" travaillé. :) – user203405

+0

Notez également que lorsque les opérations main() terminent l'ensemble du processus, de nombreux threads peuvent ne pas se terminer. Certains pourraient même ne pas commencer. – ash

1

Vous détruisez votre cadre de pile avant que vous avez rejoint les discussions en utilisant les données sur la pile. Avant d'appeler pthread_exit(), vous voulez appeler pthread_join() pour chaque thread que vous avez créé.

+0

Ok, maintenant je comprends. Merci. :) – user203405

1

Je suppose que lorsque pthread_exit() est appelée et que le thread se termine, la pile du thread n'est plus valide.

Vous avez deux choix.

  1. Utilisez pthread_join() pour attendre la fin du thread.
  2. Allouer de manière dynamique le tableau thread_data.
+0

Je pensais que pthread_exit réglerait le problème de l'attente. Ce n'est pas le cas. J'étais confus car les données étaient valides au moment où le fil a été appelé, l'information était affichée, mais quelque chose d'autre s'est produit et des déchets ont été imprimés. – user203405

Questions connexes