2010-11-11 5 views
0

C'est un programme multithread très simple. Il va créer deux threads et courir. Dans le fil, il copiera le argv0 à origname.un résultat étrange du programme pthread

Lors de la première utilisation, le origname est correct.

Mais après être entré dans la boucle while, l'origname sera corrompu par le sprintf.

Il imprimera comme:

Hello World! It's me, thread #0 ./multithread 3!

origname 0 ./multithread 3!

le contenu de origname est le paramètre pour le sprintf. Je ne comprends pas quelle est la raison. Quelqu'un peut-il aider?

#include <pthread.h> 
#include <stdio.h> 
#define NUM_THREADS  2 
void sendstring(char *string) 
{ 
    printf("%s",string); 
} 
struct thread_data{ 
    int thread_id; 
    char *argv0; 
}; 

struct thread_data thread_data_array[NUM_THREADS]; 


void *PrintHello(void *parameter) 
{ 
    struct thread_data *childpara; 
    childpara = (struct thread_data *)parameter; 
    int i = 0; 
    char origname[20]; 
    strncpy(origname, childpara->argv0,strlen(childpara->argv0)); 
    origname[strlen(childpara->argv0)] = '\0'; 
    printf("init origname %s argv0 %s\n",origname, childpara->argv0); 

    while(1) 
    { 
      printf("origname %s\n",origname); 
      sleep(1); 
      char buffer[30]; 
      sprintf(buffer,"Hello World! It's me, thread #%ld %s %d!\n", childpara->thread_id, childpara->argv0, i++); 
      sendstring(buffer); 
    } 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) 
{ 
    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].argv0 = argv[0]; 
      rc = pthread_create(&threads[t], NULL, PrintHello,(void *) &thread_data_array[t]);  

      if (rc){ 
        printf("ERROR; return code from pthread_create() is %d\n", rc); 
        exit(-1); 
      } 
    } 
    pthread_exit(NULL); 
} 

Répondre

0

Votre problème vient de cette ligne:

thread_data_array[t].argv0 = argv[0]; 

argv est défini comme char **argv (comme char *argv[]), ainsi argv [0] est un pointeur. Par conséquent, thread_data_array[t].argv0 est un alias des données dans argv. En fin de compte, les deux threads partagent la même chaîne, et tout est chamboulé. Ne me demandez pas les détails exacts de ce qui se bloque quand, parce qu'il y a un grand nombre de choses qui peuvent arriver quand vous faites cela, selon la ligne de code qui court quand. Pour cela, vous devez utiliser strcpy() à la place. De cette façon, chaque thread a sa propre copie, et les deux threads de ne pas jouer les uns avec les autres.

+0

C'est ce que je veux. Je veux utiliser argv [0] comme paramètre pour le nouveau thread créé. Je pense que ce n'est pas le problème. Je copie le contenu de ce pointeur vers l'origname, mais pas le pointeur. Quand je commente le sprintf, cela fonctionne correctement. – Zhongshu

+0

Vous devez comprendre - vous ne * copiez * pas le contenu. Vous copiez simplement le pointeur, ce qui signifie que les deux points pointent vers le même espace mémoire. Utilisez strcpy(). – riwalk

+0

En outre, il n'y a pas de sorte de sémaphore/barrière/mutex sur la sortie, donc quand vous le faites fonctionner, la sortie des deux threads sera parfois brouillée. – riwalk

2

Votre problème est un dépassement de tampon. Je compte:

Hello World! It's me, thread #0 ./multithread 3! 

à plus de 40 caractères, mais vous sprintf'ing dans un tampon de 30 octets. Après que cela est arrivé, tous les paris sont désactivés. Le résultat est indéfini. Ça pourrait tomber en panne, ça pourrait faire des choses bizarres, ça pourrait faire un nanobot et l'envoyer pour acheter du café pour toute l'équipe de développement.