简体   繁体   English

Pthread Posix素数分解得到了奇怪的结果?

[英]Pthread Posix prime factorization getting weird results?

I have this project where I recieve input from the command line such as "54 342 12" and it is suppose to make a thread for each input and have the threads return an array of integers and then the main thread is supppose to print out the different prime factorizations. 我有这个项目,我从命令行接收输入,例如“ 54 342 12”,并且假设为每个输入创建一个线程,并使线程返回整数数组,然后假定主线程打印出不同的素数分解。 however I am recieving weird output such as a bunch of zeros. 但是我收到奇怪的输出,例如一堆零。 I have no idea why and any help would be greatly appreciated. 我不知道为什么,任何帮助将不胜感激。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>


typedef struct _thread_data_t {
        int tid;
        } thread_data_t;

void *runner(void *param);

int main(int argc, char *argv[]) {

        pthread_t thr[argc];
        pthread_attr_t attr;
        int i, rc;
        //int *primeFactor;
        //primeFactor = (int *)malloc(sizeof(int)*argc);
        //thread_data_t thr_data[argc];
        printf("Prime Numbers: ");

        //Get the default attributes
        pthread_attr_init(&attr);
        //creat the thread
        for(i = 1; i < argc; ++i){
        //thr_data[i].tid = i;
        if ((rc = pthread_create(&thr[i],&attr,runner,argv[i]))){
                fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
                return EXIT_FAILURE;
                }
        }

        //Wait for the thread to exit
        for(i = 1; i < argc; ++i){
        void *returnValue;
        int r = 0;
        int x = (sizeof(returnValue) / sizeof(returnValue[0])) - 1;
        pthread_join(thr[i], &returnValue);
                for(r = 0; r < x; r++){
                //int c = (int *)returnValue[r];
                printf("%d ",  ((int *)returnValue)[r]);
                }
        }
        printf("\nComplete\n");

}

//The Thread will begin control in this function
void *runner(void *param) {
        int *primeFactors;
        int num = atoi(param);
        primeFactors = (int *)malloc(sizeof(int)*num);
        int i, j, isPrime;
        int k = 0;
        for(i=2; i<=num; i++)
        {
                if(num%i==0)
                {
                        isPrime=1;
                        for(j=2; j<=i/2; j++)
                        {
                                if(i%j==0)
                                {
                                        isPrime = 0;
                                        break;
                                }
                        }

                        if(isPrime==1)
                        {
                                primeFactors[k] = i;
                                k++;
                        }
                }
        }


        //Exit the thread
//      pthread_exit(0);

//      pthread_exit((void *)primeFactors);
        pthread_exit(primeFactors);
}

This line is a problem: 这行是个问题:

int x = (sizeof(returnValue) / sizeof(returnValue[0])) - 1;

The sizeof array / sizeof array[0] works only with pure arrays, not with pointers. sizeof array / sizeof array[0]仅适用于纯数组,不适用于指针。 Note that returnValue is a pointer, so sizeof(returnValue) does not return the size in bytes of the sequence of ints that the thread created, it gives you the number of bytes that a pointer needs to be store in memory. 请注意, returnValue是一个指针,因此sizeof(returnValue)不会返回线程创建的int序列的大小(以字节为单位),它为您提供了指针需要存储在内存中的字节数。 On x86_64 architecture it will be most likely 8, so x will be in most cases larger than the actuall number of prime factors and you would access the pointer out of bound which is why you see garbage values. 在x86_64架构上,最有可能是8,因此x在大多数情况下将大于实际的质数,并且您将访问指针超出范围,这就是为什么看到垃圾值的原因。

Because you are returning a pointer to a malloc ed location, you need to return the length as well. 因为你是返回一个指针malloc ED的位置,你需要返回的长度为好。 The best way to do it is by creating a structure for the return value and store the information there. 最好的方法是为返回值创建一个结构并将信息存储在那里。

Create a struct 创建一个结构

struct thread_result
{
    int *factors;
    size_t len;
};

and return a pointer to this struct with the information: 并使用以下信息返回指向该结构的指针:

void *runner(void *param) {
        int *primeFactors;
        int num = atoi(param);
        if(num == 0)
            pthread_exit(NULL);

        struct thread_result *res = calloc(1, sizeof *res);

        res->factors = NULL;
        res->len = 0;

        int *tmp;

        if(res == NULL)
            pthread_exit(NULL);

        int i, j, isPrime;
        int k = 0;
        for(i=2; i<=num; i++)
        {
            if(num%i==0)
            {
                isPrime=1;
                for(j=2; j<=i/2; j++)
                {
                    if(i%j==0)
                    {
                            isPrime = 0;
                            break;
                    }
                }

                if(isPrime==1)
                {
                    tmp = realloc(res->factors, (k+1) * sizeof *res->factors);
                    if(tmp == NULL)
                    {
                        free(res->factors);
                        free(res);
                        pthread_exit(NULL);
                    }
                    res->factors = tmp;

                    res->factors[k++] = i;
                    res->len = k;
                }
            }
        }


        pthread_exit(res);
}

Now you can get the values like this: 现在,您可以获取如下所示的值:

for(i = 1; i < argc; ++i){
    void *data;
    pthread_join(thr[i], &data);

    if(data == NULL)
        continue; // error in thread

    struct thread_result *res = data;

    for(size_t r = 0; r < res->len; r++){
        printf("%d ", res->factors[r]);
    }

    free(res->factors);
    free(res);
}

And don't forget to destroy the thread attributes with 而且不要忘了用销毁线程属性

pthread_attr_destroy(&attr);

before leaving main . 离开main之前。 But you are not setting any attribute to the threads, so you can creates the threads with: 但是您没有为线程设置任何属性,因此可以使用以下方法创建线程:

pthread_create(&thr[i], NULL, runner, argv[i]);

Also don't cast malloc and you have to check the return value of malloc . 另外,不要强制转换malloc而必须检查malloc的返回值。

edit 编辑

OP wrote in the comments OP在评论中写道

I think I updated all of my code correctly to match what you said but now I am recieving the error "Segmentation dump (core dumped)" Any idea on why this might be? 我认为我正确地更新了所有代码,以符合您的要求,但是现在我收到错误消息“细分转储(核心转储)”,这可能是为什么吗?

Actually no, but you must have missed something somewhere, because when I compile and run this code: 实际上没有,但是您一定错过了某些地方,因为当我编译并运行以下代码时:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>


typedef struct _thread_data_t {
        int tid;
        } thread_data_t;

void *runner(void *param);

struct thread_result
{
    int *factors;
    size_t len;
};

int main(int argc, char *argv[]) {

    pthread_t thr[argc];
    int i, rc;
    printf("Prime Numbers:\n");

    for(i = 1; i < argc; ++i){
        if ((rc = pthread_create(&thr[i],NULL,runner,argv[i]))){
            fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
            return EXIT_FAILURE;
        }
    }


    for(i = 1; i < argc; ++i){
        void *data;
        pthread_join(thr[i], &data);

        if(data == NULL)
            continue; // error in thread

        struct thread_result *res = data;

        for(size_t r = 0; r < res->len; r++){
            printf("%d ", res->factors[r]);
        }

        free(res->factors);
        free(res);

        puts("");
    }


}

void *runner(void *param) {
    int num = atoi(param);
    if(num == 0)
        pthread_exit(NULL);

    struct thread_result *res = calloc(1, sizeof *res);

    res->factors = NULL;
    res->len = 0;

    int *tmp;

    if(res == NULL)
        pthread_exit(NULL);

    int i, j, isPrime;
    int k = 0;
    for(i=2; i<=num; i++)
    {
        if(num%i==0)
        {
            isPrime=1;
            for(j=2; j<=i/2; j++)
            {
                if(i%j==0)
                {
                        isPrime = 0;
                        break;
                }
            }

            if(isPrime==1)
            {
                tmp = realloc(res->factors, (k+1) * sizeof *res->factors);
                if(tmp == NULL)
                {
                    free(res->factors);
                    free(res);
                    pthread_exit(NULL);
                }
                res->factors = tmp;

                res->factors[k++] = i;
                res->len = k;
            }
        }
    }


    pthread_exit(res);
}

I get this output: 我得到以下输出:

$ valgrind ./a 54 342 12
==17697== Memcheck, a memory error detector
==17697== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17697== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==17697== Command: ./a 54 342 12
==17697== 
Prime Numbers:
2 3 
2 3 19 
2 3 
==17697== 
==17697== HEAP SUMMARY:
==17697==     in use at exit: 0 bytes in 0 blocks
==17697==   total heap usage: 19 allocs, 19 frees, 3,640 bytes allocated
==17697== 
==17697== All heap blocks were freed -- no leaks are possible
==17697== 
==17697== For counts of detected and suppressed errors, rerun with: -v
==17697== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

which tells me that everything worked fine and that all memory has been freed as well. 告诉我,一切正常,所有内存也已释放。

So you've must have made an error when you copied & pasted the code from my answer. 因此,当您从我的答案中复制并粘贴代码时,您一定犯了一个错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM