在pthread_join腐败pthread_create的参数在栈 [英] pthread_join corrupts pthread_create argument in the stack

查看:126
本文介绍了在pthread_join腐败pthread_create的参数在栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我接到的高级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 ints 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆