简体   繁体   English

使用pthread时出现SegFault

[英]SegFault when using pthreads

I am trying to work on a project for my OS class, and I am getting a SegFault while working with pthreads, but I am not really sure what is causing the problem. 我正在尝试为我的OS类开发一个项目,并且在使用pthreads时遇到了SegFault,但是我不确定是什么引起了问题。

As for the program, I am trying to accomplish the following program : 至于程序,我正在尝试完成以下程序:

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; 狒狒越过绳子的顺序应予以保留; ie, 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. 解决此要求,以便保留FIFO顺序。 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. 即,试图向左/向右交叉的狒狒比试图向相反方向交叉的狒狒更早到达。

Basically, I am reading in a text file, and then simulating a FIFO system where some monkeys are trying to cross a rope bridge. 基本上,我正在阅读一个文本文件,然后模拟一些猴子试图越过索桥的FIFO系统。 What is weird is that I was able to get the program to run a few times, but it would frequently cause a SegFault. 奇怪的是,我能够使程序运行几次,但是它经常会导致SegFault。

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

where east_side and west_side are below. 其中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);

}

I am using a sample input in a plain text file of 我正在使用纯文本文件中的示例输入

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

This creates the output: 这将创建输出:

sh-4.3$ main input.txt 5 sh-4.3 $ main input.txt 5
The input is 输入是
LRRRRRLLR LRRRRRLLR
Baboon 1: Request to cross rope (left to right) 狒狒1:请求交叉绳索(从左到右)
Baboon 1: waiting 狒狒1:等待
Baboon 1: Cross rope request granted (Current crossing: left to right, Number of baboons on rope: 1) 狒狒1:授予交叉绳索请求(当前交叉:从左到右,绳索上的狒狒数量:1)
Baboon 2: Request to cross rope (right to left) 狒狒2:要求交叉绳索(从右到左)
Baboon 3: Request to cross rope (right to left) 狒狒3:要求交叉绳索(从右到左)
Baboon 4: Request to cross rope (right to left) 狒狒4:请求交叉绳索(从右到左)
Baboon 5: Request to cross rope (right to left) 狒狒5:请求交叉绳索(从右到左)
Baboon 1: Exit rope (Current crossing: left to right, Number of baboons on rope: 0) 狒狒1:出口绳索(当前交叉点:从左到右,绳索上的狒狒数量:0)
Baboon 2: waiting 狒狒2:等待
Baboon 2: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: 1) 狒狒2:授予交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:1)
Baboon 3: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: 2) 狒狒3:授予交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:2)
Baboon 4: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: 3) 狒狒4:授予交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:3)
Baboon 6: Request to cross rope (right to left) 狒狒6:要求交叉绳索(从右到左)
Baboon 7: Request to cross rope (left to right) 狒狒7:要求交叉绳索(从左到右)
Baboon 8: Request to cross rope (left to right) 狒狒8:请求交叉绳索(从左到右)
Baboon 9: Request to cross rope (right to left) 狒狒9:要求交叉绳索(从右到左)
Segmentation fault (core dumped) 分段故障(核心已转储)

I have included the entire file in case the problem is actually not where I think the problem is. 我已经包括了整个文件,以防问题实际上不在我认为的问题所在。

/*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);
}

running valgrind is almost imediate to detect your error: 运行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)

line 103 is pthread_join(eastern[k],NULL); 第103行是pthread_join(eastern[k],NULL); ; ; valgrind stresses that the eastern array is read while not set. valgrind强调未设置时将读取东部数组。

Your arrays are not fulfilled, you access elements that were not set. 您的数组未实现,您访问未设置的元素。 You can probably modify the join loop in this manner: 您可能可以通过以下方式修改连接循环:

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

As others in this thread have mentioned, I encountered an error with my code where i was trying to access array elements that had not been initialized properly. 正如该线程中的其他人提到的那样,我在尝试访问未正确初始化的数组元素时遇到了我的代码错误。 I am summing up my changes in this post here. 我在这里总结我的变化。 Most of the thanks go @kaylum for helping me reach this conclusion. 最感谢@kaylum帮助我得出了这个结论。

These array accesses occurred here: 这些数组访问发生在这里:

for(k;k<baboonCnt;++k)
    {

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

The improperly initializing occur in the lines 行中初始化不当

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]);
        }
    }

These two groups of code were what were causing the problems in execution, including the SegFault I was experiencing. 这两组代码是导致执行问题的原因,其中包括我遇到的SegFault。 Modifying the initialization section to instead create 2 separate arrays of ids, one referencing east baboons and the other referencing west baboons, rather than simply keeping all the ids in one group, was key to making the program work. 修改初始化部分以改为创建2个单独的ID数组,这是使程序正常运行的关键,而不是简单地将所有ID放在一个组中,一个数组引用东狒狒,另一个引用西狒狒。 After adjusting the id key storage method, the pthread_join loops also needed to be modified so that they properly accessed the arrays. 调整了id密钥存储方法后,还需要修改pthread_join循环,以便它们正确访问数组。

Here is the modified initialization section: 这是修改后的初始化部分:

int eastcnt=0, westcnt=0, eastid[eastBab], westid[westBab], i=0;
    for(i;i<baboonCnt;++i)
      {
        sleep(1);
        if(temp[i]=='L')
          {
        eastid[eastcnt]=i;
        printf("Baboon %d wants to cross left to right\n",i);
        pthread_create(&eastern[eastcnt],NULL, (void *) &east_side,(void *) &eastid[eastcnt] );
        ++eastcnt;
          }
        else if(temp[i]=='R')
          {
        westid[westcnt]=i;
        printf("Baboon %d wants to cross right to left\n",i);
        pthread_create(&western[westcnt],NULL, (void *) &west_side,(void *) &westid[westcnt] );
        ++westcnt;
          }
      }

and the modified pthread_join loops 和修改后的pthread_join循环

int k =0;
    for(k;k<westBab;++k)
    {
        pthread_join(western[k],NULL); 
    }
    k=0;
    for(k;k<eastBab;++k)
    {
        pthread_join(eastern[k],NULL); 
    }

After making the above changes, and some general cleaning up, the entire program works to specification. 进行上述更改并进行一些常规清理后,整个程序将按规范工作。

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

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