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

时间:2019-05-12 18:55:16

标签: c linux multithreading pthread-join

我尝试在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()函数?

注意:如果您运行此代码,则不关心警告,它们都与强制转换有关

1 个答案:

答案 0 :(得分:4)

不,不是不是订单。这是//Here I save my custom peripheral (left and right) import Foundation import CoreBluetooth extension CBPeripheral{ struct Holder { static var insoleService: CBService! static var temperatureEnableCharacteristic: CBCharacteristic? static var batteryLevelCharacteristic: CBCharacteristic? static var isConnected: Bool = false static var isThermalEnabled: Bool = false static var batteryLevel: Int = 0 static var userTemperature: Double = 0 static var topTemperature: Double = 0 static var midTemperature: Double = 0 static var bottomTemperature: Double = 0 static var steps: Int = 0 } var insoleService: CBService { get { return Holder.insoleService } set(newValue) { Holder.insoleService = newValue } } var temperatureEnableCharacteristic: CBCharacteristic { get { return Holder.temperatureEnableCharacteristic! } set(newValue) { Holder.temperatureEnableCharacteristic = newValue } } } 类型。将retval传递到&retval时,类型/大小错误。

pthread_joinretval时,它只有4个字节,但是[假设64位编译],int期望有指向pthread_join的8个字节的指针。

这将导致未定义的行为,因为该调用会将8个字节写入仅4个字节的变量中。其余4个字节超出了void *的大小,并可能覆盖堆栈中的任何内容

在第二个示例中,存在相同的未定义行为,但是我们只是“幸运”并得到了预期的结果(可能是因为堆栈帧中变量的顺序发生了变化,以避免UB产生意外的结果)。但是,两个人仍然拥有UB。

此外,在投射到指针或从指针投射时,我们应该使用retval而不是long [以防止编译器警告]。

这是更正的代码:

int