在pthread_join腐败pthread_create的参数在栈 [英] pthread_join corrupts pthread_create argument in the stack
问题描述
我接到的高级Linux编程的书籍这个code。当我尝试在pthread_join后执行的Linux 64位环境中的
函数调用。 which_prime
变量的值被破坏的变化(0)下的code()
在这个例子中,为什么值 which_prime
运行在pthread_join后,被破坏?
在一般我们可以使用传递给安全pthread_create的函数内部主即使我们所说的其他功能,如在pthread_join()的第四个参数
?
的#include< pthreads.h中>
#包括LT&;&stdio.h中GT;/ *计算连续的素数(效率很低)。返回
第N个质数,其中N是看重* ARG指出。 * /
无效* compute_prime(无效* ARG)
{
INT候选人= 2; INT N = *((INT *)ARG);
而(1){
INT因素;
INT is_prime = 1;
/ *通过连续师测试素性。 * /
为(系数= 2;因子所述候选++因子)
如果(候选%的因素== 0){
is_prime = 0;
打破;
}
/ *这是我们正在寻找的素数? * /
如果(is_prime){
如果(--N == 0)
/ *返回所需的素数作为线程返回值。 * /
回报(无效*)候选人;
}
++候选人;
}
返回NULL;
}诠释的main()
{
线程的pthread_t;
INT which_prime = 5000;
INT素;
/ *启动计算线程,直到第5000素数。 * /
在pthread_create(安培;螺纹,NULL,&安培; compute_prime,&安培; which_prime);
/ *做一些其他的工作,在这里... * /
/ *等待质数的线程来完成,并得到结果。 * /
在pthread_join(螺纹,(无效*)及素数);
/ *打印它计算的最大素数。 * /
的printf(%的DTH素数为%d \\ n,which_prime,素数);
返回0;
}
我们在某个时间点不再安全的之间的转换已经到达 INT
和指针
。这是因为在有些情况下指针是64位的64位系统,而是一个 INT
仅在32位。
因此,假设32位 INT
和64位指针,这里发生的事情在你的code。第二个参数在pthread_join
是一个指针到一个指针。换句话说,你应该传递指针(一个64位的值的地址)的地址。相反,你是路过的地址首要
(将一个32位值的地址)。当在pthread_join
写的结果,它会覆盖 which_prime
,因为 which_prime
如下黄金
在内存中。
要解决这个问题,你需要避免 INT
和指针之间转换。做到这一点的方法之一是避免使用的第二个参数在pthread_join
,通过以下code作为证明。
的#include<&stdio.h中GT;
#包括LT&;&pthreads.h中GT;#定义NUM_THREADS 20typedef结构
{
诠释成功;
INT输入;
INT输出;
} stData;无效* DoSomething的(无效* ARG)
{
stData * dataptr = ARG; dataptr->成功= 1;
dataptr->输出= dataptr->输入* 2;
返回NULL;
}INT主要(无效)
{
INT I;
的pthread_t ID [NUM_THREADS];
stData数据[NUM_THREADS] = {{0}}; 对于(i = 0; I< NUM_THREADS;我++)
{
数据[I]。输入I + 1 =;
在pthread_create(和ID由[i],NULL,doSomething的,与放大器;数据[I]);
} 对于(i = 0; I< NUM_THREADS;我++)
{
在pthread_join(同上[I],NULL); 如果(数据[I] .success)
的printf(线程%2D:输入=%2D输出=%2D \\ n,i + 1的数据[I]。输入,数据[I] .OUTPUT);
其他
的printf(线程%2D:失败\\ n,I + 1);
} 返回0;
}
I got this code from an advanced Linux programming book. When I try to execute the code under Linux 64bit environment the value of the which_prime
variable gets corrupted (changes to 0) after pthread_join()
function call.
In this example why the value of which_prime
gets corrupted after running pthread_join?
In general can we use the 4th argument passed to pthread_create function safely inside main even if we call other functions like pthread_join()
?
#include <pthread.h>
#include <stdio.h>
/* Compute successive prime numbers (very inefficiently). Return the
Nth prime number, where N is the value pointed to by *ARG. */
void* compute_prime (void* arg)
{
int candidate = 2;
int n = *((int*) arg);
while (1) {
int factor;
int is_prime = 1;
/* Test primality by successive division. */
for (factor = 2; factor < candidate; ++factor)
if (candidate % factor == 0) {
is_prime = 0;
break;
}
/* Is this the prime number we’re looking for? */
if (is_prime) {
if (--n == 0)
/* Return the desired prime number as the thread return value. */
return (void*) candidate;
}
++candidate;
}
return NULL;
}
int main ()
{
pthread_t thread;
int which_prime = 5000;
int prime;
/* Start the computing thread, up to the 5,000th prime number. */
pthread_create (&thread, NULL, &compute_prime, &which_prime);
/* Do some other work here... */
/* Wait for the prime number thread to complete, and get the result. */
pthread_join (thread, (void*) &prime);
/* Print the largest prime it computed. */
printf("The %dth prime number is %d.\n", which_prime, prime);
return 0;
}
We've arrived at a point in time where it is no longer safe to convert between an int
and a pointer
. That's because there are 64-bit systems where a pointer is 64-bits, but an int
is only 32-bits.
So assuming 32-bit int
and 64-bit pointer, here's what's happening in your code. The second argument to pthread_join
is a pointer-to-a-pointer. In other words, you should be passing the address of a pointer (the address of a 64-bit value). Instead, you are passing the address of prime
(the address of a 32-bit value). When pthread_join
writes the result, it overwrites which_prime
, because which_prime
follows prime
in memory.
To fix the problem, you need to avoid converting between int
s and pointers. One way to do that is to avoid using the second parameter of pthread_join
, as demonstrated by the following code.
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 20
typedef struct
{
int success;
int input;
int output;
} stData;
void *doSomething( void *arg )
{
stData *dataptr = arg;
dataptr->success = 1;
dataptr->output = dataptr->input * 2;
return NULL;
}
int main( void )
{
int i;
pthread_t id[NUM_THREADS];
stData data[NUM_THREADS] = {{0}};
for ( i = 0; i < NUM_THREADS; i++ )
{
data[i].input = i + 1;
pthread_create( &id[i], NULL, doSomething, &data[i] );
}
for ( i = 0; i < NUM_THREADS; i++ )
{
pthread_join( id[i], NULL );
if ( data[i].success )
printf( "thread %2d: input=%2d output=%2d\n", i+1, data[i].input, data[i].output );
else
printf( "thread %2d: failed\n", i+1 );
}
return 0;
}
这篇关于在pthread_join腐败pthread_create的参数在栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!