【问题标题】:Segmentation Fault when using Threads and Semaphores, Mac Vs Linux使用线程和信号量时的分段错误,Mac Vs Linux
【发布时间】:2013-04-25 20:18:09
【问题描述】:

我的问题涉及我在 linux 机器上运行此程序而不是我自己的 mac 计算机时遇到的分段错误。该程序在我自己的 Mac 计算机上运行我认为它应该的方式,但是当我尝试在我学校的 linux 计算机上运行它时,我得到一个没有出现在我的 mac 计算机上的分段错误。我将简要介绍一下作业的背景,然后更详细地讨论问题。

所以我有这个程序,它基本上模拟狒狒用一根绳子穿过峡谷。一次只能穿越一只狒狒,一次可以穿越的狒狒数量,以及在允许来自另一方向的狒狒穿越之前,可以从一个方向穿越多少只狒狒有一定的限制。代码的实现。

我已经在 stackoverflow 上搜索了分段错误问题,但其中大多数处理多个进程,而我只是使用不同的线程。分段错误最终来自等待不存在的信号量,但是当我检查它是否已初始化时,它已成功初始化。同样,这个程序可以在我的 Mac 上运行,但是当我尝试在我的 Mac 上运行它时却无法运行。任何帮助都可以理解为什么它不能在 linux 机器上运行但可以在 mac 上运行。如果需要更多信息,我很乐意提供。我有一次进行了错误检查,但该代码已从学校计算机上删除。据我记得,我的错误检查没有显示任何错误。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <pthread.h>

#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h> //for mode flags, if needed for future use

#define ATOB_COUNT 20
#define BTOA_COUNT 20
#define RANDOM_SEED 2123

//semaphore names
#define MUTEX_SEM "/mutex"
#define TOB_SEM "/toB"
#define TOA_SEM "/toA"

//define methods here if needed
void *toAThread(void *threadId);
void *toBThread(void *threadId);
void my_sleep(int limit);
void sem_open_errorCheck(char *name, unsigned int startingValue, sem_t *result);

//defining semaphores and shared variables
sem_t *mutex, *toB, *toA;
int xingCount = 0;
int xedCount = 0;
int toBWaitCount = 0;
int toAWaitCount = 0;
enum xingDirectionTypes {
    none,
    aToB,
    bToA
};
enum xingDirectionTypes xingDirection = none;

char orderLeaving[100];


struct threadInfo {
    int threadId;
};

struct threadInfo atobIDs[ATOB_COUNT];
struct threadInfo btoaIDs[BTOA_COUNT];

int main(void) {

    pthread_t atobPTHREADS[ATOB_COUNT];
    pthread_t btoaPTHREADS[BTOA_COUNT];
    pthread_attr_t attr;
    void *status;

    srandom(RANDOM_SEED);

    //call helper method which creates semaphore and errorchecks
    sem_open_errorCheck(MUTEX_SEM, (unsigned int)1, mutex);
    sem_open_errorCheck(TOA_SEM, (unsigned int)0, toA);
    sem_open_errorCheck(TOB_SEM, (unsigned int)0, toB);


    //Creating a set of attributes to send to the threads
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    //spawn toB baboons
    int counter;
    for (counter = 0; counter < BTOA_COUNT; counter++) {
        atobIDs[counter].threadId = counter;
        int result;
        if ((result = pthread_create(&atobPTHREADS[counter], &attr, toBThread, (void*) &atobIDs[counter])) == -1) {
            perror("Thread Creation Error: atob baboon");
            exit(EXIT_FAILURE);
        }
    }

    //spawn toA baboons
    for (counter = 0; counter < ATOB_COUNT; counter++) {
        btoaIDs[counter].threadId = counter + 20;
        int result;
        if ((result = pthread_create(&btoaPTHREADS[counter], &attr, toAThread, (void*) &btoaIDs[counter])) == -1) {
            perror("Thread Creation Error: btoa baboon");
            exit(EXIT_FAILURE);
        }
    }

    //Wait for all the threads to finish
    for(counter = 0; counter < ATOB_COUNT; counter++)
    {
        int result = pthread_join(atobPTHREADS[counter], &status);
        if(result == -1)
        {
            perror("Thread Join: AtoB");
            exit(EXIT_FAILURE);
        }
    }

    for(counter = 0; counter < BTOA_COUNT; counter++)
    {
        int result = pthread_join(btoaPTHREADS[counter], &status);
        if(result == -1)
        {
            perror("Thread Join: BtoA");
            exit(EXIT_FAILURE);
        }
    }
    printf("The order leaving %s", orderLeaving);
    exit(EXIT_SUCCESS);
}

void *toBThread(void *threadId) {

    struct threadInfo *info;
    info = (struct threadInfo *)threadId;
    int id = info->threadId;

    my_sleep(100); //simulate being idle for 1-100ms
    //for order checking
    char *baboonOrder;
    baboonOrder = "B ";
    strcat(orderLeaving, baboonOrder);

    sem_wait(mutex);
    if ((xingDirection == aToB || xingDirection == none) && xingCount < 5 && (xedCount + xingCount) < 10) { //there is an extra parenthesis here in the solutions
        xingDirection = aToB;
        xingCount++;
        printf("AtoB baboon (thread %d) got on the rope\n", id);
        sem_post(mutex);
    }
    else {
        toBWaitCount++;
        sem_post(mutex);
        sem_wait(toB);
        toBWaitCount--;
        xingCount++;
        xingDirection = aToB;
        printf("AtoB baboon (thread %d) got on the rope\n", id);
        sem_post(mutex);
    }
    //CROSSING


    sem_wait(mutex);
    printf("AtoB baboon (thread %d) got off the rope\n", id);
    xedCount++;
    xingCount--;
    if (toBWaitCount != 0 && (((xedCount+xingCount)<10) || ((xedCount+xingCount) >= 10 && toAWaitCount == 0))) {
        sem_post(toB);
    }
    else {
        if (xingCount == 0 && toAWaitCount != 0 && (toBWaitCount == 0 || (xedCount + xingCount)>=10)) {
            xingDirection = bToA;
            xedCount = 0;
            sem_post(toA);
        }
        else {
            if (xingCount == 0 && toBWaitCount == 0 && toAWaitCount == 0) {
                xingDirection = none;
                xedCount = 0;
                sem_post(mutex);
            }
            else {
                sem_post(mutex);
            }
        }
    }
}

/*
 baboons going from side a to side b
 */
void *toAThread(void *threadId) {

    struct threadInfo *info;
    info = (struct threadInfo *)threadId;
    int id = info->threadId;

    my_sleep(100);

    //for order checking
    char *baboonOrder;
    baboonOrder = "A ";
    strcat(orderLeaving, baboonOrder);

    sem_wait(mutex);
    if ((xingDirection == bToA || xingDirection == none) && xingCount < 5 && (xedCount + xingCount) < 10) { //there is an extra parenthesis here in the solutions
        xingDirection = bToA;
        xingCount++;
        printf("BtoA baboon (thread %d) got on the rope\n", id);
        sem_post(mutex);
    }
    else {
        toAWaitCount++;
        sem_post(mutex);
        sem_wait(toA);
        toAWaitCount--;
        xingCount++;
        xingDirection = bToA;
        printf("BtoA baboon (thread %d) got on the rope\n", id);
        sem_post(mutex);
    }
    //CROSSING


    sem_wait(mutex);
    printf("BtoA baboon (thread %d) got off the rope\n", id);
    xedCount++;
    xingCount--;
    if (toAWaitCount != 0 && (((xedCount+xingCount)<10) || ((xedCount+xingCount) >= 10 && toBWaitCount == 0))) {
        sem_post(toA);
    }
    else {
        if (xingCount == 0 && toBWaitCount != 0 && (toAWaitCount == 0 || (xedCount + xingCount)>=10)) {
            xingDirection = aToB;
            xedCount = 0;
            sem_post(toB);
        }
        else {
            if (xingCount == 0 && toAWaitCount == 0 && toBWaitCount == 0) {
                xingDirection = none;
                xedCount = 0;
                sem_post(mutex);
            }
            else {
                sem_post(mutex);
            }
        }
    }
}

//taken with permission from readers/writers problem
//Puts the calling thread to sleep to simulate both random start times and random workloads
void my_sleep(int limit) {
    struct timespec time_ns;
    int duration = random() % limit + 1;
    time_ns.tv_sec = 0;
    time_ns.tv_nsec = duration * 1000000;
    int result = nanosleep(&time_ns, NULL);
    if (result != 0)
    {
        perror("Nanosleep");
        exit(EXIT_FAILURE);
    }
}

void sem_open_errorCheck(char *name, unsigned int startingValue, sem_t *result) {

    sem_unlink(name);
    result = sem_open(name, O_CREAT, 0600, startingValue);
    if (result == -1) {
        perror("sem_open error: semaphore failed to open correctly");
        exit(EXIT_FAILURE);
    }
}

【问题讨论】:

    标签: multithreading semaphore


    【解决方案1】:

    如何调试这样的东西

    调试它的最佳方法是使用gdb 调试器运行它。像这样:

    gdb my-monkey-program
    (gdb) run
    Program received signal SIGSEGV, Segmentation fault.
    (gdb) info threads
    (gdb) bt
    

    另一个好主意是用 valgrind 运行它:

    valgrind ./my-monkey-program
    

    它会告诉你无效的内存访问和各种各样的事情。

    您的具体问题

    gdb 报告调用堆栈是:

    #0  sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:45
    #1  0x0000000000400e8d in toAThread (threadId=0x602160) at test.c:190
    #2  0x00007ffff7bc4e9a in start_thread (arg=0x7fffed7e9700) at pthread_create.c:308
    #3  0x00007ffff78f1cbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
    #4  0x0000000000000000 in ?? ()
    

    这是我编译的行号:

    187     baboonOrder = "A ";
    188     strcat(orderLeaving, baboonOrder);
    189 
    190     sem_wait(mutex);
    

    这是因为 mutex 为 NULL。

    为什么会坏

    您从未真正分配给mutex 变量。您将指针传递给sem_open_errorCheck,但您真正需要传递的是指向指针的指针。想必这同样适用于toAtoB

    它在 Mac 上运行只是运气!

    【讨论】:

      猜你喜欢
      • 2021-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 2020-02-06
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多