2010-11-14 14 views
2

Voici la fonction qui donne segfault dans pthread_join:Segmentation fault avec pthread_join


void call_merge()  
{  
    int no_runs = No_sub_seq;  
     int no_joins=no_runs-1; 
    int magic1=0,j=0,inc = 1; 
    int temp_runs = no_runs/2;   
    int i,k; 
    while(temp_runs!=0)  
    { 
     magic1=0; 
     std::list<pthread_t> threadList; 
     pthread_t thread; 
     for(i=0;i<=temp_runs-1;i++) 
     { 
        if((magic1 + inc) <= no_joins)  
        { 
         data *d=(data *)malloc(sizeof(data)); 

         d->a=magic1; 
         d->b=magic1+inc; 
         d->c=inc; 
         pthread_create(&thread,NULL,(void* (*)(void*))merge, (void*)d); 
         threadList.push_front(thread); 

        } 
        magic1 = magic1 + (inc * 2); 
     } 
     std::list<pthread_t>::iterator m; 
     for(m=threadList.begin();m!=threadList.end();m++) 
       pthread_join(*m,NULL); 
     if((no_runs % 2) != 0) 
      temp_runs++;  
     no_runs = temp_runs; 
     temp_runs = no_runs/2;  
     inc = inc * 2; 
     } 
} 

ici est la fonction de fusion


void merge(void *param) 
{ 
    data *d=(data *)param; 

    int low=Sq[d->a],high; 

    int mid=Sq[d->b]-1; 

    if(Sq[d->b + d->c]==0) 
     high=size-1; 
    else 
     high=Sq[d->b + d->c]-1; 

    int k; 

    int i=0; 
    int j=low; 

    while(j<=mid) 
     b[i++]=a[j++]; 

    i=0; k=low; 
    while (k<j && j<=high) 
     if (b[i]<=a[j]) 
      a[k++]=b[i++]; 
     else 
      a[k++]=a[j++]; 

    while (k<j) 
     a[k++]=b[i++]; 

} 

la fonction de fusion appelée dans le code ci-dessus fusionne simplement les sous-réseaux passés en utilisant les paramètres d-> a, d-> b, d-> c. et il n'y a aucun code de fil écrit dans la fonction de fusion. Le programme ci-dessus fonctionne bien lorsqu'il n'y a pas de threads et donne une séquence triée du tableau d'entrée. Quand j'ai essayé de déboguer ceci en utilisant gdb, il affiche un segault dans pthread_join(). Je suis incapable de comprendre pourquoi cela se passe donc ??? merci d'avance

+0

ne répond pas à votre question, mais puisque vous utilisez C++, vous devez allouer votre variable 'd' avec : 'data * d = nouvelles données;' c'est plus simple. N'oubliez pas de le libérer avec 'delete' et non' free'. –

Répondre

2

L'un de vos appels à pthread_create() échoue probablement, par ex. car vous dépassez la limite du nombre total de threads par processus. Dans ce cas, thread contient une valeur indéfinie. Puisque vous ignorez l'erreur, continuez et stockez cette valeur indéfinie dans votre liste, puis appelez le pthread_join() dessus plus tard, ce qui entraîne un segfault.

EDIT: Maintenant que vous gérez les erreurs de pthread_create(), le segfault est parti, mais certains de vos fils ne comprends toujours créé, donc ils ne peuvent pas effectuer leur travail. C'est pourquoi votre code fonctionne avec une plage de 1000 mais pas avec une plage de 10000.

Votre conception semble bien adaptée à thread pooling, c'est-à-dire de générer un nombre fixe de fils et de leur donner plus de travail dès qu'ils terminent leurs tâches courantes. Voir here ou there pour les implémentations de pool utilisant des threads POSIX.

+0

si (pthread_create (& thread, NULL, (void * (*) (void *)) fusionner, (void *) d) == 0) threadList.push_front (thread); – nikhil

+0

J'ai ajouté la ligne ci-dessus, mais même alors, il donne segfault – nikhil

+0

@nikhil, 'threadList' semble être global. Peut-être qu'il est corrompu (ou ses itérateurs sont invalidés) par l'un des threads? –

0

À quelle étendue définissez-vous l'objet threadList? Vous push_front les threads nouvellement créés dans la liste, mais dans votre code, je ne vois pas un erase explicite des discussions jointes, ni une suppression RAII de la liste complète des threads. Puisque vous parcourez toute la liste des threads que vous appelez probablement pthread_join plusieurs fois pour des threads déjà annulés ...