C - 使用互斥锁和线程的段错误

标签 c pthreads

我正在使用线程和互斥体。但由于某种原因,我不明白为什么,我遇到了一些段错误。无法使用 gdb,因为我无法收到该错误 =/

我还尝试在行之间进行一些打印,但看不到任何相关信息...

有人可以告诉我为什么会发生这种情况吗?

#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;
}

这是代码的一些结果!

示例 1(打印任何内容之前):

make: *** [run] Segmentation fault

示例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

示例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

最佳答案

我运行该程序

ulimit -c unlimited

这导致生成核心文件。现在什么时候可以运行 gdb。

调试此核心文件显示错误位于此行:

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

打印火车给出:

(gdb) print *train

$3 = {num = 3, from = 5, to = 2}

所以train->from无效(有效是1-4)!

train->to 和 train->from 是用generateRandom()生成的,所以bug肯定就在这里。

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

rand()%max 可以生成从 0 到 max-1 的数字。添加 min 可以得到 max+min-1。由于输入为 2 (CITY_A) 和 4 (CITY_D),因此您可以获得 2 到 5 之间的数字。您可能需要这样:

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

关于C - 使用互斥锁和线程的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37489795/

相关文章:

从 uchar* 转换为 uint* 会产生不可预测的结果

c - 未定义对 pthreads 中运行器的引用

c - 为什么 pthread_join 在最后一次迭代中失败(给出段错误)?

c - c add_before 和 add_after 函数中的链表

c - 在 C 中初始化 char **string 以在soap结构函数参数中使用

c++ - 如果参数很复杂,* 和 & 运算符的作用是什么?

c++ - C/C++ 程序有什么方法可以在 main() 之前崩溃吗?

C - pthread_create - Clang GCC 区别

c - 关于 C 中 POSIX 线程的问题

c++ - Pthread 循环函数永远不会被调用