C &引用;列车交叉互斥问题“在最后两行上获取NULL

C &引用;列车交叉互斥问题“在最后两行上获取NULL,c,mutex,C,Mutex,嘿,我在解决一个导致在最终输出中显示一些不需要的NULL的bug时遇到了问题。运行程序时,请在运行前在命令行中输入诸如“nnseeewww”之类的字符串 这是密码 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <string.h> /* mutex

嘿,我在解决一个导致在最终输出中显示一些不需要的NULL的bug时遇到了问题。运行程序时,请在运行前在命令行中输入诸如“nnseeewww”之类的字符串

这是密码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>

/* mutex */
pthread_mutex_t thisMutex;

/* Condition Variables */
sem_t nQueue, eQueue, sQueue, wQueue;
int nFirst, sFirst, eFirst, wFirst;
int done = 0;

/* Thread Prototypes */
void *bats(void *);
void *checking(void *);

/* Prototypes */
void arrive(int num, char *dir);
void cross();
void leave(int num, char *dir);
void check();

/* Global pointer to argv */
char *directions = NULL;

int main(int argc, char *argv[])
{
    int i = 0,
    n = 0,
    s = 0,
    e = 0,
    w = 0;

    directions = argv[1];
    while(  argv[1][i] == 'n' || argv[1][i] == 'e' ||
          argv[1][i] == 's' || argv[1][i] == 'w' )
    {
        if(argv[1][i] == 'n'){n++;}
        if(argv[1][i] == 's'){s++;}
        if(argv[1][i] == 'e'){e++;}
        if(argv[1][i] == 'w'){w++;}
        i++;
    }


    pthread_mutex_init(&thisMutex, NULL);
    sem_init(&nQueue, 0, n);
    sem_init(&sQueue, 0, s);
    sem_init(&eQueue, 0, e);
    sem_init(&wQueue, 0, w);
    nFirst = sFirst = eFirst = wFirst = 0;

    pthread_t tid[i];
    pthread_t checker;

    pthread_create(&checker, NULL, checking, NULL);

    for(int j = 0; j < i; j++)
    { pthread_create(&tid[j], NULL, bats, (void*) &j); }

    for(int j = 0; j < i; j++)
    { pthread_join(tid[j], NULL); }

    done = 1;

    pthread_join(checker, NULL);

    pthread_mutex_destroy(&thisMutex);
    sem_destroy(&nQueue);
    sem_destroy(&sQueue);
    sem_destroy(&wQueue);
    sem_destroy(&eQueue);

    return 0;
}


void *checking(void *arg)
{
    while( done == 0 )
    {
        if( nFirst == 1 || sFirst == 1 ||
           eFirst == 1 || wFirst == 1 )
            check();
    }
    exit(0);
}

void *bats(void *arg)
{
    int index = *(int *)arg;
    char *dir;
    switch (directions[index])
    {
        case 'n':
            dir = "North";
            break;
        case 's':
            dir = "South";
            break;
        case 'e':
            dir = "East";
            break;
        case'w':
            dir = "West";
            break;
    }
    arrive(index, dir);
    leave(index, dir);
    _exit(0);
}

/* Functions */
void arrive(int num, char *dir)
{
    printf("BAT %d from %s arrives at crossing\n", num, dir);
    if(strcmp(dir,"North")== 0)
    {
        sem_wait(&nQueue);
        nFirst = 1;
        while(eFirst == 1){ /* do nothing */ }
        cross();
        nFirst = 0;
        sem_post(&nQueue);
    }
    else if(strcmp(dir,"West")== 0)
    {
        sem_wait(&wQueue);
        wFirst = 1;
        while(nFirst == 1){ /* do nothing */ }
        cross();
        wFirst = 0;
        sem_post(&wQueue);
    }
    else if(strcmp(dir,"South")== 0)
    {
        sem_wait(&sQueue);
        sFirst = 1;
        while(wFirst == 1){ /* do nothing */ }
        cross();
        sFirst = 0;
        sem_post(&sQueue);
    }
    else if(strcmp(dir,"East")== 0)
    {
        sem_wait(&eQueue);
        eFirst = 1;
        while(sFirst == 1){ /* do nothing */ }
        cross();
        eFirst= 0;
        sem_post(&eQueue);
    }
}

void cross()
{
    pthread_mutex_lock(&thisMutex);
    sleep(1);
    pthread_mutex_unlock(&thisMutex);;
}

void leave(int num, char *dir)
{
    printf("BAT %d from %s leaving crossing\n", num, dir);
}

void check()
{
    if( nFirst == 1 && sFirst == 1 &&
       eFirst == 1 && wFirst == 1 )
    {
        eFirst = 0;
        sleep(1);
        eFirst = 1;
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
/*互斥*/
pthread_mutex_t this mutex;
/*条件变量*/
sem_t nQueue、eQueue、sQueue、wQueue;
int nFirst、sFirst、eFirst、wFirst;
int done=0;
/*螺纹原型*/
无效*蝙蝠(无效*);
作废*检查(作废*);
/*原型*/
无效到达(int num,char*dir);
无效交叉();
无效休假(整数,字符*dir);
无效检查();
/*指向argv的全局指针*/
char*directions=NULL;
int main(int argc,char*argv[])
{
int i=0,
n=0,
s=0,
e=0,
w=0;
方向=argv[1];
而(argv[1][i]='n'| | argv[1][i]='e'||
argv[1][i]='s'| | argv[1][i]='w')
{
如果(argv[1][i]='n'){n++;}
如果(argv[1][i]='s'){s++;}
if(argv[1][i]='e'){e++;}
if(argv[1][i]='w'){w++;}
i++;
}
pthread_mutex_init(&thisMutex,NULL);
sem_init(&nQueue,0,n);
sem_init(&sQueue,0,s);
sem_init(&等式,0,e);
sem_init(&wQueue,0,w);
nFirst=sFirst=eFirst=wFirst=0;
pthread_t tid[i];
线程检测器;
pthread_创建(&checker,NULL,checking,NULL);
对于(int j=0;j
本作业的目标是

  • 从同一方向到达的蝙蝠排在已经到达十字路口的第一只蝙蝠后面

  • 从右侧到达的蝙蝠始终拥有优先通行权(除非等待的蝙蝠收到出发信号)

  • 必须防止僵局

  • 必须防止饥饿

  • 运行代码后,您将看到最后两行中蝙蝠到达的方向为“NULL”。需要帮助来解决这个问题吗

    谢谢

  • dir
    是一个字符指针。因此,您不能直接使用等号,如
    if(dir==“North”)
    您需要的是
    if(strcmp(dir,North”)==0)

  • 在下面的循环中

    while(  argv[1][i] == 'n' || argv[1][i] == 'e' ||
          argv[1][i] == 's' || argv[1][i] == 'w' )
    {
        i++;
        if(argv[1][i] == 'n'){n++;}
        if(argv[1][i] == 's'){s++;}
        if(argv[1][i] == 'e'){e++;}
        if(argv[1][i] == 'w'){w++;}
    }
    

  • 您在循环中首先递增
    i
    。因此,对于数组中的最后一个元素
    argv[1][i]
    ,您正在读取垃圾值。
    i
    的递增应该是循环中的最后一条语句。即在
    if(argv[1][i]='w'){w++;}

    您的程序有未定义的行为,因为您正在将指向局部变量的指针传递到线程函数中。在
    bats
    函数中,取消引用指针时,您可能会得到垃圾值:

       for(int j = 0; j < i; j++)
        { 
          pthread_create(&tid[j], NULL, bats, (void*) &j); 
        }
    
    请记住在
    bats
    功能中释放此内存:

    void *bats(void *arg)
    {
        int index = *(int *)arg;
        //...
        leave(index, dir);
        free (arg); // <--
        pthread_exit(NULL); // instead of _exit(0);
    }
    
    void*bats(void*arg)
    {
    int index=*(int*)arg;
    //...
    休假(索引,目录);
    
    free(arg);//
    dir
    是一个
    char
    指针。因此不能直接使用像
    if(dir==“North”)
    这样的等号。您需要的是
    if((strcmp(dir,“North”)==0)
    我替换了if语句,仍然得到空值错误进行了这些更改,现在我在最后一个'Arrival'语句中仍然得到空值,之后出现分段错误OK,我将新代码粘贴到原始帖子中。请查看是否仍然有错误,谢谢!谢谢!解决了空值问题。我看到程序的最后一行说“BAT 0 from North Leving crossing”0为什么要等到最后才离开?@BobbyWidThaTool
    \u exit(0)
    在加入第一个线程时关闭程序,你应该调用
    pthread\u exit(NULL)
    而不是_exit(0)。你是一个传奇人物。谢谢!现在运行得很好。我希望我擅长C
    void *bats(void *arg)
    {
        int index = *(int *)arg;
        //...
        leave(index, dir);
        free (arg); // <--
        pthread_exit(NULL); // instead of _exit(0);
    }