【问题标题】:Pthread Posix prime factorization getting weird results?Pthread Posix 素数分解得到奇怪的结果?
【发布时间】:2018-03-05 04:22:01
【问题描述】:

我有这个项目,我从命令行接收输入,例如“54 342 12”,假设为每个输入创建一个线程并让线程返回一个整数数组,然后主线程应该打印出不同的素数分解。但是我收到了奇怪的输出,例如一堆零。我不知道为什么,任何帮助将不胜感激。

#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);
}

【问题讨论】:

  • 欢迎来到 Stack Overflow!请阅读Why is “Can someone help me?” not an actual question?。寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括期望的行为特定问题或错误以及重现它所需的最短代码问题本身。没有明确的问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example
  • 你没有数组,你有一个指向分配内存的指针。 sizeof(returnValue) 会给你 4 或 8,这取决于你的系统架构,不管它实际指向多少内存。您需要从命令行捕获大小并使用main 中的大小循环访问内存。这会很好看:c-faq.com/aryptr/index.html

标签: c arrays pthreads posix


【解决方案1】:

这一行有问题:

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

sizeof array / sizeof array[0] 仅适用于纯数组,不适用于 指针。注意 returnValue 是一个指针,所以 sizeof(returnValue) 是 不返回线程创建的整数序列的字节大小,它 为您提供指针需要存储在内存中的字节数。在 x86_64 架构很可能是 8,所以x 在大多数情况下是 大于素数的实际数量,您将访问指针 超出范围,这就是您看到垃圾值的原因。

因为您要返回指向malloced 位置的指针,所以您需要返回 长度也是如此。最好的方法是创建一个结构 返回值并将信息存储在那里。

创建一个结构

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

并返回一个指向该结构的指针和信息:

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);
}

现在你可以得到这样的值:

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);
}

别忘了用

销毁线程属性
pthread_attr_destroy(&attr);

在离开之前main。但是您没有为线程设置任何属性,所以 您可以使用以下方法创建线程:

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

还有don't cast malloc,你必须检查返回值 malloc.

编辑

OP 写在 cmets 中

我认为我正确更新了所有代码以匹配您所说的,但现在我收到错误“分段转储(核心转储)”您知道为什么会这样吗?

实际上没有,但你一定在某个地方漏掉了什么,因为当我 编译并运行这段代码:

#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);
}

我得到这个输出:

$ 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)

这告诉我一切正常,并且所有内存都已被释放为 好吧。

所以你在复制粘贴我的代码时一定犯了一个错误 回答。

【讨论】:

  • 嘿 Pablo 非常感谢您的帮助!我想我正确更新了所有代码以匹配您所说的,但现在我收到错误“分段转储(核心转储)”您知道为什么会这样吗?除此之外,它现在没有给我任何输出。
  • 好吧,听起来很棒,很抱歉我打错了错误,它是“分段错误(核心转储)”。当你说“也不要强制转换 malloc,你必须检查 malloc 的返回值”时,我不完全理解你想让我做什么,所以除非它在你给我的代码中,否则我没有为此做任何改变.
  • @ColbyBarton 我已经更新了我的答案,我的代码是正确的,我发布了我编译并运行的代码。
  • 感激不尽。我缺少一些小东西。再次感谢您,非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2022-01-25
  • 2020-10-08
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
相关资源
最近更新 更多