我们可以在调用 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;
}
我尝试在 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;
}