我们可以在调用 pthread-create() 函数之前定义一个变量吗

can we define a variable before calling pthread-create() function

我尝试在 C 语言和 Manjaro 上测试多线程 OS。 我写了一小段代码,但我遇到了一个奇怪的问题

我执行了下面的简单代码,但没有得到预期的结果:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define THREADS 4

void *routine1(void * x)
{
    int result =2;
    pthread_exit((void *)result);
}

int main ()
{
    int sum=0;
    int retval=0;
   pthread_t threads[THREADS];
    for ( int i=0;i<THREADS;i++)
        pthread_create(&threads[i], NULL, routine1, (void *)i );
   for (int i=0; i<THREADS; i++)
   {
     pthread_join(threads[i],&retval);
     sum+=retval;
   }
   printf("%d\n",sum);
   return 0;

}

以上代码的结果是:

2

但我希望在输出中看到 8 个值。调试了几个小时后,我发现如果我在 pthread_create() 函数之后声明 sum 变量,代码通常会 运行:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define THREADS 4

void *routine1(void * x)
{
    int result =2;
    pthread_exit((void *)result);
}

int main ()
{
    int retval=0;
   pthread_t threads[THREADS];
   for ( int i=0;i<THREADS;i++)
   pthread_create(&threads[i], NULL, routine1, (void *)i );
   int sum=0;
   for (int i=0; i<THREADS; i++)
   {
        pthread_join(threads[i],&retval);
        sum+=retval;
   }
   printf("%d\n",sum);
   return 0;
}

代码的输出是:

 8

正确答案。

我想知道为什么第一个密码是错误的?这是因为 pthread_create() 函数?

注意:如果您 运行 此代码不关心警告,它们都是关于转换

不,不是订单。它是 retval 类型 。当,把&retval传给pthread_join,就错了type/sizeof.

retval是一个int时,它只有4个字节,但是[假设64位编译],pthread_join需要一个指向void *的指针,它是8字节。

这会导致未定义的行为,因为调用会将 8 个字节写入一个只有 4 个字节的变量。剩余的 4 个字节超出了 retval 的大小,可能会覆盖堆栈上的 任何内容

在你的第二个例子中有相同的未定义行为,但我们只是 "got lucky" 并得到了预期的结果 [可能是因为堆栈帧中变量的顺序发生了变化以避免 UB 产生意外结果].但是,两人都还有UB。

此外,在转换 to/from 指针时,我们应该使用 long 而不是 int [以防止编译器警告]。

这是更正后的代码:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define THREADS 4

void *
routine1(void *x)
{
#if 0
    int result = 2;
#else
    long result = 2;
#endif

    pthread_exit((void *) result);
}

int
main()
{
    int sum = 0;
#if 0
    int retval = 0;
#else
    void *retval;
#endif
    pthread_t threads[THREADS];

#if 0
    for (int i = 0; i < THREADS; i++)
        pthread_create(&threads[i], NULL, routine1, (void *) i);
#else
    for (long i = 0; i < THREADS; i++)
        pthread_create(&threads[i], NULL, routine1, (void *) i);
#endif

    for (int i = 0; i < THREADS; i++) {
        pthread_join(threads[i], &retval);
#if 0
        sum += retval;
#else
        sum += (long) retval;
#endif
    }

    printf("%d\n", sum);

    return 0;

}