2016-05-27 14 views
0

Ich verwende Threads und Mutex damit. Aber aus irgendeinem Grund kann ich nicht herausfinden warum, ich bekomme einige Segmentierungsfehler. Kann nicht gdb verwenden, weil ich nicht diesen Fehler bekommen =/C - Segmentierungsfehler mit Mutex und Threads

Auch habe ich versucht, einige Drucke zwischen den Zeilen zu machen, sondern alle relevanten Informationen nicht sehen können ...

Kann mein jemand sagen, warum ist das passiert?

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

// Not order for easy random implementation 
#define CITY_B 1 
#define CITY_A 2 
#define CITY_C 3 
#define CITY_D 4 
#define TRAIN_NUMBER 3 

pthread_mutex_t lineAB; 
pthread_mutex_t lineBC; 
pthread_mutex_t lineBD; 

typedef struct { 
    int num; 
    int from; 
    int to; 
}Train; 

int generateRandom(int min, int max, int seed) { 
    srand(time(NULL)+seed); 
    return ((rand()%max)+min); 
} 

char * getCurrentTime() { 
    char * timeString = (char *) malloc(sizeof(char) * 20); 
    time_t now = time(NULL); 
    strftime(timeString, 20, "%H:%M:%S", localtime(&now)); 
    return timeString; 
} 

char * hora() { 
    return getCurrentTime(); 
} 

pthread_mutex_t * nextLine(int from, int to) { 
    switch(from) { 
     case CITY_A: { 
      return &lineAB; 
     } 
     case CITY_B: { 
      switch(to) { 
       case CITY_A: { 
        return &lineAB; 
       } 
       case CITY_C: { 
        return &lineBC; 
       } 
       case CITY_D: { 
        return &lineBD; 
       } 
      } 
      break; 
     } 
     case CITY_C: { 
      return &lineBC; 
     } 
     case CITY_D: { 
      return &lineBD; 
     } 
    } 
} 

char * getCityName(int num) { 
    switch(num) { 
     case CITY_A: { 
      return "City A"; 
     } 
     case CITY_B: { 
      return "City B"; 
     } 
     case CITY_C: { 
      return "City C"; 
     } 
     case CITY_D: { 
      return "City D"; 
     } 
    } 
} 

char * getLineName(int from, int to) { 
    switch(from) { 
     case CITY_A: { 
      return "cityA-cityB"; 
      break; 
     } 
     case CITY_B: { 
      switch(to) { 
       case CITY_A: { 
        return "cityA-cityB"; 
        break; 
       } 
       case CITY_C: { 
        return "cityB-cityC"; 
        break; 
       } 
       case CITY_D: { 
        return "cityB-cityD"; 
        break; 
       } 
      } 
      break; 
     } 
     case CITY_C: { 
      return "cityB-cityC"; 
      break; 
     } 
     case CITY_D: { 
      return "cityB-cityD"; 
      break; 
     } 
    } 
} 

void * threadFunc(void *arg){ 
    Train * train = (Train*)arg; 
    /*int trainNum = info[0]; 
    int from = info[1]; 
    int to = info[2];*/ 
    char * partida = hora(); 
    char * chegada; 

    printf("Train %d, From: %s, To: %s\n", train->num, getCityName(train->from), getCityName(train->to)); 

    //printf("A\n"); 
    pthread_mutex_t * myMutex = nextLine(train->from, CITY_B); 
    pthread_mutex_lock(myMutex); 
    //printf("B\n"); 
    printf("Train: %d\tLine: %s\tFrom: %s\tTo: %s\n", train->num, 
     getLineName(train->from, CITY_B), getCityName(train->from), getCityName(train->to)); 
    // Each line takes x sec to finish 
    //printf("C\n"); 
    sleep(3); 
    //printf("D\n"); 
    pthread_mutex_unlock(myMutex); 
    //printf("E\n"); 
    myMutex = nextLine(CITY_B, train->to); 
    //printf("F\n"); 
    printf("Train: %d\tLine: %s\tFrom: %s\tTo: %s\n", train->num, 
     getLineName(CITY_B, train->to), getCityName(train->from), getCityName(train->to)); 
    // Each line takes x sec to finish 
    //printf("G\n"); 
    sleep(3); 
    //printf("H\n"); 
    pthread_mutex_unlock(myMutex); 
    //printf("I\n"); 
    chegada = hora(); 
    //printf("J\n"); 
    printf("\nTrain: %d\nDeparture: %s\tArrival: %s\n\n", train->num, partida, chegada); 
    //printf("K\n"); 
    pthread_exit((void*)NULL); 
} 

int main(char *arg, char **args){ 
    pthread_t threads[TRAIN_NUMBER]; 
    Train trains[TRAIN_NUMBER]; 

    lineAB = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; 
    lineBC = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; 
    lineBD = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; 

    srand(time(NULL)); 
    int i; 
    for (i = 0; i < TRAIN_NUMBER; ++i) { 
     trains[i].num = i+1; 
     trains[i].from = generateRandom(CITY_A, CITY_D, i); 
     if(trains[i].from == CITY_A) { 
      trains[i].to = generateRandom(CITY_C, CITY_D, i); 
     } else { 
      trains[i].to = CITY_A; 
     } 
     pthread_create(&threads[i],NULL,threadFunc,(void*)&trains[i]); 
    } 

    for(i = 0; i < TRAIN_NUMBER; i++) { 
     pthread_join(threads[i], NULL); 
    } 

    pthread_mutex_destroy(&lineAB); 
    pthread_mutex_destroy(&lineBC); 
    pthread_mutex_destroy(&lineBD); 

    return 0; 
} 

Hier sind einige Ergebnisse des Codes!

Beispiel 1 (Vor allem Druck):

make: *** [run] Segmentation fault 

Beispiel 2:

Train 1, From: City D, To: City A 
Train: 1 Line: cityB-cityD From: City D To: City A 
Train 3, From: City D, To: City A 
make: *** [run] Segmentation fault 

Beispiel 3:

Train 1, From: City A, To: City C 
Train: 1 Line: cityA-cityB From: City A To: City C 
Train 2, From: City A, To: City C 
Train 3, From: City C, To: City A 
Train: 3 Line: cityB-cityC From: City C To: City A 
Train: 1 Line: cityB-cityC From: City A To: City C 
Train: 3 Line: cityA-cityB From: City C To: City A 
Train: 2 Line: cityA-cityB From: City A To: City C 
Train: 2 Line: cityB-cityC From: City A To: City C 

Train: 1 Departure: 18:51:55 Arrival: 18:52:01 

Train: 3 Departure: 18:51:55 Arrival: 18:52:01 

Train: 2 Departure: 18:51:55 Arrival: 18:52:04 
+0

beim Kompilieren immer alle Warnungen aktivieren, diese Warnungen beheben. (für 'gcc', bei minimaler Verwendung:' -Wall -Wextra -pedantic' verwende ich auch '-Wconversions -std = gnu99') Unter anderem Probleme mit dem geposteten, code, den Funktionen:' nextline() ',' getCityName() ',' getLineName() 'haben Ausführungspfade, die keinen Wert zurückgeben, aber diese Funktionen sind alle so deklariert, dass sie einen Wert – user3629249

+0

(cont) die Signatur für die Funktion zurückliefern:' main() 'hat zwei Parameter nicht verwendet werden, schlagen Sie vor: 'int main (void)' BTW: Wenn die 2-Parameter-Signatur für 'main()' verwendet wird, hat der erste Parameter immer den Typ 'int' – user3629249

+0

der Prototyp für' sleep() 'fehlt die entsprechende Header-Datei fehlt. Die Anweisung muss eingefügt werden: '#include ' – user3629249

Antwort

1

ich das Programm lief mit

ulimit -c unbegrenzt

Dies führte zur Erzeugung einer Kerndatei. Jetzt kann gdb laufen.

Debuggen dieser Kern Datei zeigt den Fehler in dieser Zeile:

printf("Train %d, From: %s, To: %s\n", train->num, getCityName(train->from), getCityName(train->to)); 

Printing Zug gibt:

(GDB) print * Zug

3 $ = {num = 3, von = 5, bis = 2}

Also Zug-> aus ist ungültig (gültig ist 1-4)!

train-> zu und train-> von wird mit generateRandom() generiert, so dass der Fehler hier sein muss.

int generateRandom(int min, int max, int seed) { 
    srand(time(NULL)+seed); 
    return ((rand()%max)+min); 
} 

rand()% max kann eine Zahl von 0 bis max-1 generieren. Das Hinzufügen von min kann max + min-1 ergeben. Da Eingänge 2 (CITY_A) und 4 (CITY_D) Sie Zahlen zwischen 2 erhalten und 5. Sie wollen wahrscheinlich Sie stattdessen:

int generateRandom(int min, int max, int seed) { 
    srand(time(NULL)+seed); 
    return ((rand()%(max-min))+min); 
} 
0

der entsandte Code viele Probleme enthält, von denen die meisten in den Kommentaren angezeigt werden .

Das Hauptproblem liegt in der generateRandom() Funktion jedoch an dieser Linie:

return ((rand()%max)+min); 

die Werte erzeugt, die größer als 3 (5 typisch ist)

dann später in dem Code, Der Zugriff auf das Mutex-Array erfolgt über das Ende des Arrays hinaus.

Dann wird der Aufruf an pthread_mutex_lock() einen ungültigen Zeiger zugeführt, was zu dem Seg-Fehlerereignis führt.

Zwei Pässe mit dem gdb Debugger zusammen mit einigen "nützlichen" Anrufe zu printf() schnell die Ursache des Problems gefunden.

Wir empfehlen Ihnen dringend, sich mit einem Debugger vertraut zu machen.

hier ist die Version des Codes, die ich für das Debuggen verwendet:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> // rand(), srand() 
#include <unistd.h> 

// Not order for easy random implementation 
#define CITY_B 1 
#define CITY_A 2 
#define CITY_C 3 
#define CITY_D 4 
#define TRAIN_NUMBER 3 

pthread_mutex_t lineAB = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t lineBC = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t lineBD = PTHREAD_MUTEX_INITIALIZER; 

struct TrainStruct 
{ 
    size_t num; 
    size_t from; 
    size_t to; 
}; 

typedef struct TrainStruct Train; 


size_t generateRandom(int min, int max, size_t seed) 
{ 
    (void)seed; 
    //srand(time(NULL)+seed); 
    return (size_t)((rand()%max)+min); 
} 


char * getCurrentTime() 
{ 
    char * timeString = malloc(20); 
    time_t now = time(NULL); 
    strftime(timeString, 20, "%H:%M:%S", localtime(&now)); 
    return timeString; 
} // end function: getCurrentTime 


char * hora() { 
    return getCurrentTime(); 
} 

pthread_mutex_t * nextLine(size_t from, size_t to) 
{ 
    switch(from) 
    { 
     case CITY_A: 
      return &lineAB; 
      break; 

     case CITY_B: 
      switch(to) 
      { 
       case CITY_A: 
        return &lineAB; 
        break; 

       case CITY_C: 
        return &lineBC; 
        break; 

       case CITY_D: 
        return &lineBD; 
        break; 

       default: 
        printf("invalid train.to: %lu\n", to); 
        return NULL; 
        break; 
      } // end switch 
      break; 

     case CITY_C: 
      return &lineBC; 
      break; 

     case CITY_D: 
      return &lineBD; 
      break; 

     default: 
      printf("invalid train.from: %lu\n", from); 
      return NULL; 
      break; 
    } // end switch 
} 


char * getCityName(size_t num) 
{ 
    switch(num) 
    { 
     case CITY_A: 
      return "City A"; 
      break; 

     case CITY_B: 
      return "City B"; 
      break; 

     case CITY_C: 
      return "City C"; 
      break; 

     case CITY_D: 
      return "City D"; 
      break; 

     default: 
      printf("invalid city num: %lu\n", num); 
      return NULL; 
      break; 
    } // end switch 
} 


char * getLineName(size_t from, size_t to) 
{ 
    switch(from) 
    { 
     case CITY_A: 
      return "cityA-cityB"; 
      break; 

     case CITY_B: 
      switch(to) 
      { 
       case CITY_A: { 
        return "cityA-cityB"; 
        break; 
       } 
       case CITY_C: 
        return "cityB-cityC"; 
        break; 

       case CITY_D: 
        return "cityB-cityD"; 
        break; 

       default: 
        printf("invalid train.to: %lu\n", to); 
        return NULL; 
        break; 
      } // end switch 
      break; 

     case CITY_C: 
      return "cityB-cityC"; 
      break; 

     case CITY_D: 
      return "cityB-cityD"; 
      break; 

     default: 
      printf("invalid train.from: %lu\n", from); 
      return NULL; 
      break; 
    } // end switch 
} 


void * threadFunc(void *arg) 
{ 
    Train * train = (Train*)arg; 
    /*int trainNum = info[0]; 
    int from = info[1]; 
    int to = info[2];*/ 
    char * partida = hora(); 
    char * chegada; 

    // for testing 
    printf("func:%s\n num: %lu\n from: %lu\n to: %lu\n\n", 
      __func__, 
      train->num, 
      train->from, 
      train->to); 

    printf("Train %lu, From: %s, To: %s\n\n", 
     train->num, 
     getCityName(train->from), 
     getCityName(train->to)); 

    //printf("A\n"); 
    pthread_mutex_t * myMutex = nextLine(train->from, CITY_B); 
    pthread_mutex_lock(myMutex); 
    //printf("B\n"); 
    printf("Train: %lu\tLine: %s\tFrom: %s\tTo: %s\n", 
     train->num, 
     getLineName(train->from, CITY_B), 
     getCityName(train->from), 
     getCityName(train->to)); 

    // Each line takes x sec to finish 
    //printf("C\n"); 
    sleep(3); 
    //printf("D\n"); 
    pthread_mutex_unlock(myMutex); 


    //printf("E\n"); 
    myMutex = nextLine(CITY_B, train->to); 
    //printf("F\n"); 
    printf("Train: %lu\tLine: %s\tFrom: %s\tTo: %s\n", 
     train->num, 
     getLineName(CITY_B, train->to), 
     getCityName(train->from), 
     getCityName(train->to)); 

    // Each line takes x sec to finish 
    //printf("G\n"); 
    sleep(3); 
    //printf("H\n"); 
    pthread_mutex_unlock(myMutex); 


    //printf("I\n"); 
    chegada = hora(); 
    //printf("J\n"); 
    printf("\nTrain: %lu\nDeparture: %s\tArrival: %s\n\n", 
     train->num, 
     partida, 
     chegada); 
    //printf("K\n"); 
    pthread_exit((void*)NULL); 
} 

int main(void) 
{ 
    pthread_t threads[TRAIN_NUMBER]; 
    Train trains[TRAIN_NUMBER]; 



    srand((unsigned)time(NULL)); 

    for (size_t i = 0; i < TRAIN_NUMBER; ++i) 
    { 
     trains[i].num = i+1; 
     trains[i].from = generateRandom(CITY_A, CITY_D, i); 

     if(trains[i].from == CITY_A) 
     { 
      trains[i].to = generateRandom(CITY_C, CITY_D, i); 
     } 

     else 
     { 
      trains[i].to = CITY_A; 
     } 

     pthread_create(&threads[i],NULL,threadFunc,(void*)&trains[i]); 
    } 

    for(size_t i = 0; i < TRAIN_NUMBER; i++) 
    { 
     pthread_join(threads[i], NULL); 
    } 

    pthread_mutex_destroy(&lineAB); 
    pthread_mutex_destroy(&lineBC); 
    pthread_mutex_destroy(&lineBD); 
} // end function: main