【问题标题】:pthreads: inconsistency between gcc and icc on Linuxpthreads:Linux上gcc和icc之间的不一致
【发布时间】:2009-11-06 07:40:35
【问题描述】:

以下代码使用 gcc (4.1.2 20080704) 生成错误且不一致的输出,但使用 icc (Version 11.1) 生成正确且预期的输出。但是,当我将 thread_data_array[] 定义从 main() 移动到全局时(紧接在 struct thread_data 定义之后),它在两个编译器中都可以正常工作。我不明白为什么这种变化会产生任何影响。我想递归地生成线程,所以我需要从函数中调用它,但不定义为全局的。有人可以解释一下代码有什么问题吗?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 4

struct thread_data {
    int  thread_id;
    int  sum;
};

/* struct thread_data thread_data_array[NUM_THREADS]; */

void *p_task(void *threadarg)
{
    struct thread_data *my_data;
    int taskid;
    int sum;

    my_data = (struct thread_data *) threadarg;
    taskid = my_data->thread_id;
    sum = my_data->sum;

    printf("Thread #%d with sum %d\n", taskid, sum);

    for ( sum = 0; sum < 000000000; sum++ ) {
        for ( taskid = 0; taskid < 000000000; taskid++ ) {
            sum+=taskid;
        }
    }

    return my_data;
}

int main ()
{
    struct thread_data thread_data_array[NUM_THREADS]; /*this does not work*/

    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    for ( t = 0; t < NUM_THREADS; t++ ) {
        thread_data_array[t].thread_id = t;
        thread_data_array[t].sum = (int) t*2;
        rc = pthread_create( &threads[t], NULL, p_task, (void *) &thread_data_array[t] );
    }

    pthread_exit(NULL);

    return 0;

}

【问题讨论】:

  • gcc 版本 4.4.1 没有观察到“问题”。这可能是 GCC 中的错误吗?较早的一个是 CentOS 的最新版本,所以这让我想知道......
  • 作为一个小问题,所有问题都应该有一个“这就是我所期望的”部分和一个“这就是实际发生的事情”部分:-)

标签: c linux pthreads


【解决方案1】:

嗯,我的第一个想法是主线程实际上正在退出,并在其他线程完成之前将其堆栈帧带走。根据我对 pthreads 的记忆(这是十多年前,在 DCE 中使用它们),除了堆栈大小之外,主线程绝对没有什么特别之处。

如果数组被声明为全局数组,从main 的退出不会对其产生任何影响,但如果它在main 的堆栈帧中,我会在它退出后非常小心地使用它。

我部分地基于猜测,因为您实际上并没有解释您所看到的行为是什么。

我建议在main 中的pthread_exit 之前插入以下代码:

for (t = 0; t < NUM_THREADS; t++ )
    pthread_join (threads[t], NULL);

【讨论】:

  • 另外请注意,当 main() 退出时,整个进程都会终止,因此许多线程可能无法完成。有些甚至可能还没有开始。
【解决方案2】:

在使用堆栈上的数据加入线程之前销毁堆栈帧。

在调用 pthread_exit() 之前,您需要为您创建的每个线程调用 pthread_join()。

【讨论】:

  • 好的,现在我明白了。谢谢。 :)
【解决方案3】:

我怀疑当调用 pthread_exit() 并且线程退出时,线程的堆栈不再有效。

你有两个选择。

  1. 使用 pthread_join() 等待线程完成。
  2. 动态分配thread_data数组。

【讨论】:

  • 我认为 pthread_exit 可以解决等待问题。它没有。我很困惑,因为在调用线程时数据是有效的,显示了信息,但是发生了其他事情并且正在打印垃圾。
猜你喜欢
  • 2014-04-11
  • 1970-01-01
  • 2020-02-26
  • 2023-03-04
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 2018-08-08
相关资源
最近更新 更多