c - 使用 pthread 时出现 SegFault

标签 c pthreads

我正在尝试为我的操作系统类开发一个项目,并且在使用 pthread 时遇到 SegFault,但我不太确定是什么导致了问题。

至于程序,我正在尝试完成以下程序:

There is a deep canyon somewhere in Kruger National Park, South Africa, and a single rope that spans the canyon. Baboons can cross the canyon by swinging hand- over-hand on the rope, but if two baboons going in opposite directions meet in the middle, they will fight and drop to their deaths. Furthermore, the rope is only strong enough to hold three baboons. If there are more baboons on the rope at the same time, it will break. Assuming that we can teach the baboons to use semaphores, we would like to design a synchronization scheme with the following properties.

  1. Once a baboon has begun to cross, it is guaranteed to get to the other side without running into a baboon going the other way.
  2. There are never more than three baboons on the rope. The order of the baboons crossing the rope should be preserved; i.e., the order in which they enter the rope should be the order in which they exit the rope.
  3. A continuing stream of baboons crossing in one direction should not bar baboons going the other way indefinitely (no starvation). Solve this requirement such that the FIFO order is preserved. That is, a baboon trying to cross to the left/right that arrives earlier than a baboon trying to cross in the opposite direction gets on the rope first.

基本上,我正在读取一个文本文件,然后模拟一个 FIFO 系统,其中一些猴子试图穿过绳索桥。 奇怪的是,我能够让程序运行几次,但它经常会导致 SegFault。

pthread_create(&eastern[i],NULL,(void *) &east_side,(void *)&id[i]);
pthread_create(&western[i],NULL,(void *) &west_side,(void *)&id[i]);

其中 east_side 和 west_side 位于下方。

void* east_side(void*arg)            
{
    int baboon = *(int*)arg;
    int on_rope;
    sem_wait(&deadlock_protection);
    sem_wait(&east_mutex);
    east++;
    if (east == 1)
    {
        sem_wait(&rope);
        printf("Baboon %d: waiting\n", baboon);
    }
    sem_post(&east_mutex);
    sem_post(&deadlock_protection);
    sem_wait(&counter);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Cross rope request granted (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon,3-on_rope);
    sleep(travel_time);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Exit rope (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
    sem_post(&counter);
    sem_wait(&east_mutex);
    east--;
    if (east == 0)
        sem_post(&rope);
    sem_post(&east_mutex);
}

//thread handling west to east travel
void* west_side(void*arg)    
{
    int baboon = *(int*)arg;
    int on_rope;
    sem_wait(&deadlock_protection);
    sem_wait(&west_mutex);
    west++;
    if (west == 1)
    {
        sem_wait(&rope);
        printf("Baboon %d: waiting\n", baboon);
    }
    sem_post(&west_mutex);
    sem_post(&deadlock_protection);
    sem_wait(&counter);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 3-on_rope);
    sleep(travel_time);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Exit rope (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
    sem_post(&counter);
    sem_wait(&west_mutex);
    west--;
    if (west == 0)
        sem_post(&rope);
    sem_post(&west_mutex);

}

我正在使用纯文本文件中的示例输入

L,R,R,R,R,R,L,L,R

这将创建输出:

sh-4.3$主输入.txt 5
输入为
L R R R R R L L R
狒狒1:请求交叉绳子(从左到右)
狒狒1:WAITING
狒狒1:已批准交叉绳索请求(当前交叉:从左到右,绳索上的狒狒数量:1)
狒狒2:请求交叉绳子(从右到左)
狒狒3:请求交叉绳子(从右到左)
狒狒4:请求交叉绳子(从右到左)
狒狒5:请求交叉绳子(从右到左)
狒狒1:导出绳(当前交叉口:从左到右,绳上狒狒数量:0)
狒狒2:WAITING
狒狒2:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:1)
狒狒3:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:2)
狒狒4:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:3)
狒狒6:请求交叉绳子(从右到左)
狒狒7:请求交叉绳子(从左到右)
狒狒8:请求交叉绳子(从左到右)
狒狒9:请求交叉绳子(从右到左)
段错误(核心转储)

我已经包含了整个文件,以防问题实际上不是我认为的问题所在。

/*include header files*/

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
//#include <stdbool.h>


//compile with command 
//gcc -o main *.c -lpthread -lrt

/*semaphores*/
sem_t rope;
sem_t east_mutex;
sem_t west_mutex;
sem_t deadlock_protection;
sem_t counter;

/*global variables*/
int east = 0;
int west = 0;
int travel_time;    

/*function prototypes*/
void crossing(int x);
void* east_side(void*);
void* west_side(void*);

/*main function*/
int main(int argc, char *argv[])
{ 

    char c;
    int baboonCnt=0;
    char temp[100];

    sem_init(&rope,0,1);                        //ensure mutual exclusion on rope ownership
    sem_init(&east_mutex,0,1);                  //east side on travel
    sem_init(&west_mutex,0,1);                  //west side on travel
    sem_init(&deadlock_protection,0,1);         //used to prevent deadlocks while using semaphores
    sem_init(&counter,0,3);                     //ensure only 3 baboons are allowed on the rope

    //ensure all input arguements are entered
    if ( argc == 3 )                    
    {
        travel_time = atoi(argv[2]);
        FILE *file;
        int baboonCnt=0;
        if (file = fopen(argv[1], "r") )
        {
            while((c=getc(file))!=EOF)
            {
                if(c == 'L'|| c == 'R')
                {
                    temp[baboonCnt] = c;
                    baboonCnt++;
                }
            }
        }
        else   
        {
            printf("Unable to read data from the input file.");
            return 0;
        }
        printf("The input is\n");
        int j=0;
        for(j;j<baboonCnt;++j)
        {
            printf("%c ",temp[j]);
        }
        printf("\n");
        int id[baboonCnt];
        pthread_t eastern[baboonCnt],western[baboonCnt];
        int i=0;
        for(i;i<baboonCnt;++i)
        {
            sleep(1);
            if(temp[i]=='L')
            {
                id[i] = i+1;
                printf("Baboon %d: Request to cross rope (left to right)\n", i+1);
                pthread_create(&eastern[i],NULL,(void *) &east_side,(void *)&id[i]);
            }
            else if(temp[i]=='R')
            {
                id[i] = i+1;
                printf("Baboon %d: Request to cross rope (right to left)\n", i+1);
                pthread_create(&western[i],NULL,(void *) &west_side,(void *)&id[i]);
            }
        }
        int k=0;
        printf("before k loop");
        for(k;k<baboonCnt;++k)
        {

            pthread_join(eastern[k],NULL);
            printf("eastern",k);
            pthread_join(western[k],NULL); 
            printf("western %d",k);         
        }

        //destroy all semaphores
        sem_destroy (&rope); 
        sem_destroy (&east_mutex);
        sem_destroy (&west_mutex);
        sem_destroy (&deadlock_protection);
        sem_destroy (&counter);
        return 0;
    }
    else
    {
        printf("Proper command line usage is: \n<name> <filename> <cross time>\n");
    }
}
//thread handling the east to west to travel
void* east_side(void*arg)            
{
    int baboon = *(int*)arg;
    int on_rope;
    sem_wait(&deadlock_protection);
    sem_wait(&east_mutex);
    east++;
    if (east == 1)
    {
        sem_wait(&rope);
        printf("Baboon %d: waiting\n", baboon);
    }
    sem_post(&east_mutex);
    sem_post(&deadlock_protection);
    sem_wait(&counter);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Cross rope request granted (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon,3-on_rope);
    sleep(travel_time);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Exit rope (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
    sem_post(&counter);
    sem_wait(&east_mutex);
    east--;
    if (east == 0)
        sem_post(&rope);
    sem_post(&east_mutex);
}

//thread handling west to east travel
void* west_side(void*arg)    
{
    int baboon = *(int*)arg;
    int on_rope;
    sem_wait(&deadlock_protection);
    sem_wait(&west_mutex);
    west++;
    if (west == 1)
    {
        sem_wait(&rope);
        printf("Baboon %d: waiting\n", baboon);
    }
    sem_post(&west_mutex);
    sem_post(&deadlock_protection);
    sem_wait(&counter);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 3-on_rope);
    sleep(travel_time);
    sem_getvalue(&counter, &on_rope);
    printf("Baboon %d: Exit rope (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
    sem_post(&counter);
    sem_wait(&west_mutex);
    west--;
    if (west == 0)
        sem_post(&rope);
    sem_post(&west_mutex);
}

最佳答案

运行 valgrind 几乎可以立即检测到您的错误:

==10217== Use of uninitialised value of size 8
==10217==    at 0x4E39241: pthread_join (in /usr/lib64/libpthread-2.18.so)
==10217==    by 0x400E64: main (example.c:103)

第 103 行是 pthread_join(eastern[k],NULL);; valgrind 强调东部数组在未设置时被读取。

您的数组未满足,您访问未设置的元素。 您可以通过这种方式修改连接循环:

for(k;k<baboonCnt;++k)
{
    if(temp[k]=='L') {
            pthread_join(eastern[k],NULL);
            printf("eastern %d\n",k);
    }
    else if(temp[k]=='R') {
            pthread_join(western[k],NULL);
            printf("western %d\n",k);
    }
}

关于c - 使用 pthread 时出现 SegFault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33853480/

相关文章:

c++ - 使用线程检查c++中是否存在进程

c++ - 如何避免等待信号已发送的 pthread_cond_t

c++ - 结构初始化

c - C 中的文件结尾 (EOF)

c - Pipe() with fork() with recursion : File Descriptors handling

c - pthread_self() 没有返回有意义的线程 ID?

c - 带 void* 的 Pthread 结构参数

c - 使用 sscanf() 从一行中仅输出 2 个标记

c - 悬空的 else 查询(或阅读不良代码的练习)

c++ - 在创建 OpenCL 上下文之前设置线程亲和性会导致段错误