简体   繁体   English

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

[英]C - Segmentation fault using mutex and threads

I'm using threads and mutex with it. 我正在使用线程和互斥锁。 But for some reason, i can't figure out why, i get some segmentation faults. 但是由于某些原因,我不知道为什么,但是遇到了一些分段错误。 Can't use gdb because i cannot get that error =/ 无法使用gdb,因为我无法获取该错误= /

Also i tried to make some prints between lines but cannot see any relevant information... 我也尝试在行之间进行一些打印,但看不到任何相关信息...

Can someone tell my why is this happening ? 有人可以告诉我为什么会这样吗?

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

Here are some results of the code ! 这是代码的一些结果!

Example 1 (Before printing anything): 示例1(打印任何内容之前):

make: *** [run] Segmentation fault

Example 2: 范例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

Example 3: 范例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

I ran the program with 我用

ulimit -c unlimited ulimit -c无限

this caused a core file to be generated. 这导致生成核心文件。 Now whe can run gdb. 现在可以运行gdb了。

Debugging this core file shows the error is at this line: 调试此核心文件显示错误在以下行:

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

Printing train gives: 印刷火车给:

(gdb) print *train (gdb)打印*火车

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

So train->from is invalid (valid is 1-4)! 所以train-> from是无效的(有效值为1-4)!

train->to and train->from is generated with generateRandom(), so the bug must be here. train-> to和train-> from是通过generateRandom()生成的,因此该错误必须在此处。

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

rand()%max can generate number from 0 to max-1. rand()%max可以生成从0到max-1的数字。 Adding min to this can give max+min-1. 将min添加到此可以得到max + min-1。 Since inputs are 2 (CITY_A) and 4 (CITY_D) you can get numbers between 2 and 5. You probably want this instead: 由于输入是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);
}

the posted code contains LOTS of problems, most of which are indicated in the comments. 已发布的代码包含很多问题,大部分已在注释中指出。

However, the main problem is in the generateRandom() function at this line: 但是,主要问题是在此行的generateRandom()函数中:

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

which is generating values that are greater than 3 (5 being typical) 生成的值大于3(典型值为5)

Then, later in the code, the access to the mutex array is accessing beyond the end of the array. 然后,在代码的后面,对互斥锁数组的访问将超出数组末尾。

Then the call to pthread_mutex_lock() is being fed an invalid pointer, resulting in the seg fault event. 然后,对pthread_mutex_lock()的调用被提供了无效的指针,从而导致seg故障事件。

Two passes with the gdb debugger along with some 'useful' calls to printf() quickly located the source of the problem. gdb调试器的两次传递以及对printf()一些“有用”调用迅速找到了问题的根源。

Strongly suggest you become very familiar with a debugger. 强烈建议您对调试器非常熟悉。

here is the version of the code that I used for debugging: 这是我用于调试的代码版本:

#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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM