Pthreads:分段错误

发布于 2024-10-21 07:00:18 字数 7043 浏览 1 评论 0原文

我有几个问题。这是我第一次真正尝试制作多线程程序。

注意 - 完整的程序位于页面底部

(编译,使用

g++ -pthread -o <executable file name> <sourcefile>.cpp -fpermissive

我使用 Ubuntu Studio 10.10 64 位编译它。

这个程序最大的问题是它给我带来了分段错误。

这似乎是由我在 int main() 中注释的行引起的。如果我注释掉该行,它不会给我一个分段错误错误。

为了方便起见,这里单独使用 int main() :

int main()
{
    pthread_attr_t attr;
    pthread_t threads[30];

    /* Initialize mutex and condition variable objects */
    pthread_mutex_init(&direction_mutex, NULL); 
    pthread_mutex_init(&arrive_mutex,NULL);


    pthread_cond_init (&count_threshold, NULL); 
    pthread_cond_init(&arrive_done, NULL);

    /*
     For portability, explicitly create threads in a joinable state

     I'll take your word for it on that one.
     */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( int x = 0 ; x < 30 ; x++)
   {
      long random = rand();
      int direction;

       if (random < RAND_MAX/2)
       {
            direction = 0;
       }

       else
       {
            direction = 1;
       }

       directions[x] = direction;
       printf("%d",direction);
    }

    printf("\n");

    currdir = directions[0];

    for(int j = 0 ; j < 30 ; j++)
    {
        if(j != 0)
        {
            pthread_cond_wait(&arrive_done, NULL); // THIS line of code is what is causing the problem
        }



        pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
    }

    /* Wait for all threads to complete */
    for (j = 0; j < 30; j++) 
    {
        pthread_join(threads[j], NULL);
    }

    printf("test\n");

    /* Clean up and exit */
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&direction_mutex);
    pthread_cond_destroy(&count_threshold);
    pthread_exit (NULL);

}

如果没有该行,程序将运行,但问题是,它的线程顺序似乎相当随机。

我试图使用该互斥锁来阻止 int main() 启动新线程,直到最后一个线程完成,因为该程序应该让线程按 FIFO 顺序运行。

如果没有此代码,它的行为会有所不同。

大多数时候,它从线程 0 开始,然后转到线程 3,4,有时甚至是 5,然后再返回线程 1。

有时,它从线程 3 开始,然后转到线程 4,然后线程 0...我可以不明白为什么要这样做。

每次线程执行的顺序都不同,但它永远不会像需要的那样是 0,1,2,3,4

这是注释掉有问题的行的输出:

*** Output of program with "pthread_cond_wait(&arrive_done, NULL);" commented out:


101110010101011111010001000010
ArriveBridge(): Car 1 goes accross the bridge
ExitBridge(): car 1 has left the bridge
Arrivebridge(): Thead 0 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 0 goes accross the bridge
ExitBridge(): car 0 has left the bridge
Arrivebridge(): Thead 5 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 5 goes accross the bridge
ExitBridge(): car 5 has left the bridge
Arrivebridge(): Thead 3 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 3 goes accross the bridge
ExitBridge(): car 3 has left the bridge
ArriveBridge(): Car 2 goes accross the bridge
ExitBridge(): car 2 has left the bridge
ArriveBridge(): Car 4 goes accross the bridge
ExitBridge(): car 4 has left the bridge
Arrivebridge(): Thead 6 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 6 goes accross the bridge
ExitBridge(): car 6 has left the bridge
Arrivebridge(): Thead 7 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 7 goes accross the bridge
ExitBridge(): car 7 has left the bridge
Arrivebridge(): Thead 8 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 8 goes accross the bridge
ExitBridge(): car 8 has left the bridge
Arrivebridge(): Thead 9 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 9 goes accross the bridge
ExitBridge(): car 9 has left the bridge
Arrivebridge(): Thead 10 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 10 goes accross the bridge
ExitBridge(): car 10 has left the bridge
Arrivebridge(): Thead 11 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 11 goes accross the bridge
ExitBridge(): car 11 has left the bridge
ArriveBridge(): Car 13 goes accross the bridge
ExitBridge(): car 13 has left the bridge
Arrivebridge(): Thead 12 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 12 goes accross the bridge
ExitBridge(): car 12 has left the bridge
Arrivebridge(): Thead 14 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 14 goes accross the bridge
ExitBridge(): car 14 has left the bridge
ArriveBridge(): Car 15 goes accross the bridge
ExitBridge(): car 15 has left the bridge
ArriveBridge(): Car 16 goes accross the bridge
ExitBridge(): car 16 has left the bridge
Arrivebridge(): Thead 18 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 18 goes accross the bridge
ExitBridge(): car 18 has left the bridge
Arrivebridge(): Thead 17 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 17 goes accross the bridge
ExitBridge(): car 17 has left the bridge
ArriveBridge(): Car 19 goes accross the bridge
ExitBridge(): car 19 has left the bridge
Arrivebridge(): Thead 21 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 21 goes accross the bridge
ExitBridge(): car 21 has left the bridge
ArriveBridge(): Car 20 goes accross the bridge
ExitBridge(): car 20 has left the bridge
ArriveBridge(): Car 22 goes accross the bridge
ExitBridge(): car 22 has left the bridge
Arrivebridge(): Thead 23 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 23 goes accross the bridge
ExitBridge(): car 23 has left the bridge
Arrivebridge(): Thead 24 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 24 goes accross the bridge
ExitBridge(): car 24 has left the bridge
ArriveBridge(): Car 25 goes accross the bridge
ExitBridge(): car 25 has left the bridge
ArriveBridge(): Car 26 goes accross the bridge
ExitBridge(): car 26 has left the bridge
ArriveBridge(): Car 27 goes accross the bridge
ExitBridge(): car 27 has left the bridge
ArriveBridge(): Car 29 goes accross the bridge
ExitBridge(): car 29 has left the bridge
Arrivebridge(): Thead 28 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 28 goes accross the bridge
ExitBridge(): car 28 has left the bridge
test

这是没有注释掉该行的输出

****output of program before commenting pthread_cond_wait(&arrive_done, NULL); out:


101110010101011111010001000010
Segmentation fault

正如您所看到的,在创建任何线程之前,它几乎立即失败。

我试图改进的另一件事是我的零和一序列不是很随机。有没有更好的方法来生成随机数?它不必非常随机,但这个序列每次都完全相同。

感谢您抽出时间

I have a couple questions. This is my first real attempt at making a multithreaded program.

NOTE - the full program is at the bottom of the page

(to compile, use

g++ -pthread -o <executable file name> <sourcefile>.cpp -fpermissive

)

I compiled it using Ubuntu Studio 10.10 64 bit.

The biggest problem with this program is that it gives me a segmentation fault.

It seems to be caused by the line I commented in int main(). If I comment that line out, it doesn't give me a segmentation fault error.

Here's int main() alone for convenience:

int main()
{
    pthread_attr_t attr;
    pthread_t threads[30];

    /* Initialize mutex and condition variable objects */
    pthread_mutex_init(&direction_mutex, NULL); 
    pthread_mutex_init(&arrive_mutex,NULL);


    pthread_cond_init (&count_threshold, NULL); 
    pthread_cond_init(&arrive_done, NULL);

    /*
     For portability, explicitly create threads in a joinable state

     I'll take your word for it on that one.
     */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( int x = 0 ; x < 30 ; x++)
   {
      long random = rand();
      int direction;

       if (random < RAND_MAX/2)
       {
            direction = 0;
       }

       else
       {
            direction = 1;
       }

       directions[x] = direction;
       printf("%d",direction);
    }

    printf("\n");

    currdir = directions[0];

    for(int j = 0 ; j < 30 ; j++)
    {
        if(j != 0)
        {
            pthread_cond_wait(&arrive_done, NULL); // THIS line of code is what is causing the problem
        }



        pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
    }

    /* Wait for all threads to complete */
    for (j = 0; j < 30; j++) 
    {
        pthread_join(threads[j], NULL);
    }

    printf("test\n");

    /* Clean up and exit */
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&direction_mutex);
    pthread_cond_destroy(&count_threshold);
    pthread_exit (NULL);

}

Without that line, the program runs, but the problem is, it seems to go rather randomly in thread order.

I was trying to use that mutex lock to keep int main() from starting a new thread until the last one finished, since this program is supposed to have the threads run in FIFO order.

Without this code, it varies in behavior.

Most of the time it starts at thread 0, then goes to thread 3,4, sometimes even 5 before coming back to thread 1.

Sometimes, it starts at thread 3, then goes to thread 4, then thread 0... I can't figure out why it's doing that.

It's a different sequence of thread execution every time, but it's never 0,1,2,3,4 like it needs to be

Here's the output with the offending line commented out:

*** Output of program with "pthread_cond_wait(&arrive_done, NULL);" commented out:


101110010101011111010001000010
ArriveBridge(): Car 1 goes accross the bridge
ExitBridge(): car 1 has left the bridge
Arrivebridge(): Thead 0 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 0 goes accross the bridge
ExitBridge(): car 0 has left the bridge
Arrivebridge(): Thead 5 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 5 goes accross the bridge
ExitBridge(): car 5 has left the bridge
Arrivebridge(): Thead 3 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 3 goes accross the bridge
ExitBridge(): car 3 has left the bridge
ArriveBridge(): Car 2 goes accross the bridge
ExitBridge(): car 2 has left the bridge
ArriveBridge(): Car 4 goes accross the bridge
ExitBridge(): car 4 has left the bridge
Arrivebridge(): Thead 6 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 6 goes accross the bridge
ExitBridge(): car 6 has left the bridge
Arrivebridge(): Thead 7 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 7 goes accross the bridge
ExitBridge(): car 7 has left the bridge
Arrivebridge(): Thead 8 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 8 goes accross the bridge
ExitBridge(): car 8 has left the bridge
Arrivebridge(): Thead 9 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 9 goes accross the bridge
ExitBridge(): car 9 has left the bridge
Arrivebridge(): Thead 10 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 10 goes accross the bridge
ExitBridge(): car 10 has left the bridge
Arrivebridge(): Thead 11 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 11 goes accross the bridge
ExitBridge(): car 11 has left the bridge
ArriveBridge(): Car 13 goes accross the bridge
ExitBridge(): car 13 has left the bridge
Arrivebridge(): Thead 12 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 12 goes accross the bridge
ExitBridge(): car 12 has left the bridge
Arrivebridge(): Thead 14 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 14 goes accross the bridge
ExitBridge(): car 14 has left the bridge
ArriveBridge(): Car 15 goes accross the bridge
ExitBridge(): car 15 has left the bridge
ArriveBridge(): Car 16 goes accross the bridge
ExitBridge(): car 16 has left the bridge
Arrivebridge(): Thead 18 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 18 goes accross the bridge
ExitBridge(): car 18 has left the bridge
Arrivebridge(): Thead 17 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 17 goes accross the bridge
ExitBridge(): car 17 has left the bridge
ArriveBridge(): Car 19 goes accross the bridge
ExitBridge(): car 19 has left the bridge
Arrivebridge(): Thead 21 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 21 goes accross the bridge
ExitBridge(): car 21 has left the bridge
ArriveBridge(): Car 20 goes accross the bridge
ExitBridge(): car 20 has left the bridge
ArriveBridge(): Car 22 goes accross the bridge
ExitBridge(): car 22 has left the bridge
Arrivebridge(): Thead 23 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 23 goes accross the bridge
ExitBridge(): car 23 has left the bridge
Arrivebridge(): Thead 24 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 24 goes accross the bridge
ExitBridge(): car 24 has left the bridge
ArriveBridge(): Car 25 goes accross the bridge
ExitBridge(): car 25 has left the bridge
ArriveBridge(): Car 26 goes accross the bridge
ExitBridge(): car 26 has left the bridge
ArriveBridge(): Car 27 goes accross the bridge
ExitBridge(): car 27 has left the bridge
ArriveBridge(): Car 29 goes accross the bridge
ExitBridge(): car 29 has left the bridge
Arrivebridge(): Thead 28 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 28 goes accross the bridge
ExitBridge(): car 28 has left the bridge
test

This is the output WITHOUT that line commented out

****output of program before commenting pthread_cond_wait(&arrive_done, NULL); out:


101110010101011111010001000010
Segmentation fault

As you can see, it fails almost immediately, before any threads are created.

The other thing I was trying to improve is that my sequence of zeros and ones is not very random. Is there a better way to get random numbers generated? It doesn't have to be extremely random, but this sequence is exactly the same every time.

Thanks for your time

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

人间不值得 2024-10-28 07:00:19

您实际上需要将互斥体传递给pthread_cond_wait,您正在传递NULL

对于随机数据(至少在 Linux 上),从 /dev/random/dev/urandom 读取。您还可以尝试: direction = (rand() >> 8) & 1

You need to actually pass a mutex to pthread_cond_wait, you're passing NULL.

For random data (at least on linux) read from /dev/random or /dev/urandom. You can also try: direction = (rand() >> 8) & 1

懷念過去 2024-10-28 07:00:19

你的主循环应该是:

pthread_mutex_lock(&arrive_mutex);
for(int j = 0 ; j < 30 ; j++)
{
    if(j != 0)
    {
        // Pass a locked mutex as the second parameter.
        pthread_cond_wait(&arrive_done, &arrive_mutex);
        // This releases the lock and suspends the thread.
        // When the condition variable is signaled. It re-establishes the lock
        // then releases the thread. If another processes is holding the lock
        // the released thread is stalled until it can acquire the lock.
        //
        // This means the child thread should acquire the lock on the mutex.
        // call signal and then release the lock. If the child does not
        // aquire the lock first then there is the potential for the child to
        // reach the signal before the parent waits() if this happens then the
        // parent will suspend forever (as nobody else will signal).

    }

    pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
}
// Unlock the mutex afterwords.
pthread_mutex_unlock(&arrive_mutex);

Your main loop should be:

pthread_mutex_lock(&arrive_mutex);
for(int j = 0 ; j < 30 ; j++)
{
    if(j != 0)
    {
        // Pass a locked mutex as the second parameter.
        pthread_cond_wait(&arrive_done, &arrive_mutex);
        // This releases the lock and suspends the thread.
        // When the condition variable is signaled. It re-establishes the lock
        // then releases the thread. If another processes is holding the lock
        // the released thread is stalled until it can acquire the lock.
        //
        // This means the child thread should acquire the lock on the mutex.
        // call signal and then release the lock. If the child does not
        // aquire the lock first then there is the potential for the child to
        // reach the signal before the parent waits() if this happens then the
        // parent will suspend forever (as nobody else will signal).

    }

    pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
}
// Unlock the mutex afterwords.
pthread_mutex_unlock(&arrive_mutex);
静赏你的温柔 2024-10-28 07:00:19

我认为您需要将互斥体而不是 NULL 传递给 pthread_cond_wait 。 手册页指出:

int pthread_cond_wait(pthread_cond_t *限制 cond,
pthread_mutex_t *限制互斥体);

这些函数以原子方式释放互斥体并导致调用线程在条件变量cond上阻塞;原子地在这里意味着“原子地相对于另一个线程访问互斥体然后访问条件变量”。

它试图用代码原样释放一个空互斥体。

I think you need to pass in a mutex instead of NULL to pthread_cond_wait. The man page states:

int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);

These functions atomically release mutex and cause the calling thread to block on the condition variable cond; atomically here means "atomically with respect to access by another thread to the mutex and then the condition variable".

It's trying to release a null mutex with the code the way it is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文