我无法弄清楚我的指针在做什么。导致分段错误。我确信问题出在我使用的指针数组和我正在使用的pthread_join上。
目标是将多个整数读入gcc编译器,然后打印出具有所有因子的整数,例如12:2 2 3
我创建了一个结构,该结构包含一个int数组以存储每个整数的因数(当factor函数将其拉开时)和一个counter(numfact)来存储数组中存储了多少个因数。
我在底部注释掉了打印出因素的部分。
我认为问题是我如何尝试将pthread_join的输出存储在指针数组ptr []中。每当我注释掉它时,都不会出现细分错误。 要么我以我不理解的方式弄乱了指针,要么无法使用指针数组。无论哪种方式,几个小时后,我都会被卡住。
请帮助。
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
struct intfact
{
long int factors[100];
int numfact;
};
struct intfact *factor(long int y)
{
struct intfact threadfact;
threadfact.numfact = 0;
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
threadfact.factors[threadfact.numfact] = 2;
threadfact.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
threadfact.factors[threadfact.numfact] = i;
threadfact.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
threadfact.factors[threadfact.numfact] = y;
threadfact.numfact++;
}
struct intfact *rtnthred = &threadfact;
return rtnthred;
}
/* Trial Division Function */
void *divde(void *n)
{
long int *num = (long int *) n;
struct intfact *temp = factor(*num);
return temp;
}
/* Main Function */
int main(int argc, char *argv[])
{
pthread_t threads[argc-1];
void *ptr[argc-1];
/* loop to create all threads */
for(int i=0; i < argc; i++)
{
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
}
/* loop to join all threads */
for(int i=0; i < argc; i++)
{
pthread_join(threads[i],(void *) ptr[i]); //THIS POINTER IS THE PROBLEM
}
/* loops to print results of each thread using pointer array*/
//for(int i = 0; i < argc; i++)
//{
// printf("%s: ", argv[i+1]); /* print out initial integer */
// struct intfact *temp = (struct intfact *) ptr[i]; //cast void pointer ptr as struct intfact pointer
// printf("%d", temp->numfact);
//for(int j = 0; j < temp->numfact; j++) /*(pull the numfact(count of factors) from the struct intfact pointer??)*/
//{
// printf("%d ", temp->factors[j]); /* print out each factor from thread struct */
//}
}
}
在我的Linux)终端中,此代码存储在p3.c中
“ ./ p3 12”应为“ 12:2 2 3”
答案 0 :(得分:1)
对于初学者:
这里
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
您定义一个long int
并将其作为参数传递给线程。例如12
然后在线程函数中
void *divde(void *n)
{
long int *num = (long int *) n;
您将传入的long int
视为指向long int
的指针。
然后在这里取消引用
... = factor(*num);
因此,这个*num
例如将变成*12
。那就是引用内存地址12
读出其内容并将其传递给factor)
。除了这很可能是无效地址这一事实之外,没有任何相关存储,至少没有您的代码定义。
要(或多或少地修复)此操作
void *divde(void *n)
{
long int num = (long int) n;
... = factor(num);
评论中提到了第二个问题:Multiple threads to find prime factors of integers, segmentation fault
您要解决的问题是并行编程的一种特殊情况,即并行运行的任务是完全独立的。在这种情况下,赋予每个任务自己的上下文是有意义的。这里的上下文将包括
在C语言中,可以使用结构对变量进行分组,因为您的实现已经针对任务的输出提出了>
struct intfact
{
long int factors[100];
int numfact;
};
因此缺少的是线程ID和输入。只需添加这样的示例。
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
现在在启动线程之前定义所需的上下文:
int main(int argc, char *argv[])
{
size_t num_to_process = argv - 1;
struct context ctx[num_to_process];
然后创建传递所需内容的线程,将其与输出的空间/内存一起输入:
for (size_t i = 0; i < num_to_process ; i++)
{
ctx[i].io.input = atol(argv[i]);
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
在线程函数内部,将收到的void
指针转换回其实型:
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
定义处理函数以获取指向上下文特定的输入/输出变量的指针:
void factor(struct inout * pio) /* No need to return any thing */
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pio->input directly. */
用threadfact
替换所有其他pio->output
的出现。
使用
return;
}
离开处理功能。
然后在线程函数内部调用处理函数:
factor(pio);
使用
return NULL;
}
离开线程功能。
在main()
中加入而不会从线程中得到任何结果:
/* loop to join all threads */
for (size_t i = 0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
将所有内容放在一起:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
struct intfact
{
long int factors[100];
size_t numfact;
};
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
void factor(struct inout * pio)
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pinout->input directly. */
if (0 == y)
{
return; /* Nothing to do! */
}
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
pio->output.factors[pio->output.numfact] = 2;
pio->output.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
pio->output.factors[pio->output.numfact] = i;
pio->output.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
pio->output.factors[pio->output.numfact] = y;
pio->output.numfact++;
}
return;
}
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
factor(pio);
return NULL;
}
int main(int argc, char *argv[])
{
size_t num_to_process = argc - 1;
struct context ctx[num_to_process];
for (size_t i = 0; i < num_to_process; i++)
{
ctx[i].io.input = atol(argv[i+1]);
if (!ctx[i].io.input)
{
fprintf(stderr, "COnversion to integer failed or 0 for '%s'\n", argv[i]);
}
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
/* loop to join all threads */
for (size_t i=0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
/* loops to print results of each thread using pointer array*/
for(size_t i = 0; i < num_to_process; i++)
{
printf("%ld: ", ctx[i].io.input); /* print out initial integer */
printf("%zu factors --> ", ctx[i].io.output.numfact);
for(size_t j = 0; j < ctx[i].io.output.numfact; j++)
{
printf("%ld ", ctx[i].io.output.factors[j]); /* print out each factor from thread struct */
}
putc('\n', stdout);
}
}