我正在努力理解线程,并且遇到了我似乎无法纠正的分段错误。我已将错误的范围缩小到pthread_join()
函数,但似乎无法再进一步了。我的理解是for循环必须与pthread_create()
的循环相同,并且传入的变量是传递给pthread_exit()
函数的取消引用的指针。任何方向将不胜感激。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//void *runner(void *param);
void *pFactor(void *param)
{
int *pFArray = malloc(sizeof(int) *32);
int myNum = atoi(param);
int count = 0;
printf("I'm getting here");
while (myNum % 2 == 0)
{
pFArray[count] = 2;
myNum = myNum/2;
count++;
}
for (int i = 3; i < sqrt(myNum); i += 2)
{
while (myNum % i == 0)
{
pFArray[count] = i;
myNum = myNum/i;
count++;
}
}
if (myNum > 2)
{
pFArray[count] = myNum;
}
//int *arrPtr = (int*) malloc(10);
//arrPtr = pFArray;
//return (void *) arrPtr;
//return fprint("I made it to the end of the pFactor function")
pthread_exit(pFArray);
}
int main(int argc, char *argv[])
{
pthread_t tid[argc];
pthread_attr_t attr;
if (argc == 0)
{
fprintf(stderr, "usage: a.out <integer value>\n");
return -1;
}
if (argc < 0)
{
fprintf(stderr, "%d must be >= 0\n", atoi(argv[1]));
return -1;
}
/* Get the default attributes */
pthread_attr_init(&attr);
/* Create the thread */
for (int i = 1; i < argc; i++)
{
tid[i] = i;
pthread_create(&tid[i], &attr, pFactor, &argv[i]);
printf("still working\n");
}
printf("still working\n");
/* Wait for the thread to exit */
for (int i = 1; i < argc; i++)
{
tid[i] = i;
void *my_Ptr;
printf("still working 1\n");
pthread_join(tid[i], &my_Ptr);
printf("still working 2\n");
for (;;)
{
printf("%d", atoi(argv[i]));
printf(": %d",((int*) my_Ptr)[i-1]);
}
//printf("%d", atoi(argv[i]));
//printf(": %d",((int*) my_Ptr)[i-1]);
} /*This is where you want to pass in the sum variable*/
}
答案 0 :(得分:1)
在valgrind
下运行程序可确认您诊断为在调用pthread_join
时出现问题。也可以通过在调试器中运行它来确定,但是Valgrind通常对于段错误特别有用,因为它的内存使用分析通常也可以帮助确定问题的原因。
但是,在这种情况下,主要问题很明显:您使用无效的第一个参数调用pthread_join()
。您似乎有点误会:
我的理解是for循环必须与一个相同
pthread_create()
不,不一定。与pthread_create
的唯一重要关联是,第一个参数(线程ID)必须是pthread_create()
存储的值,用于标识既未分离也未加入的线程。在与启动线程的循环类似的循环中执行连接可能是适当的,但这取决于应用程序的特定要求。但是,通常,这些要求包括所有工作线程在主线程经过某个点之前完成,并且要实现这一点,必须将每个工作线程都加入。
,传入的变量是 被取消引用的指针传递到pthread_exit() 功能。
当我知道pthread_join()
的行为时,我可以将这些单词压缩为合适的形状。我自己会说得更像是:“第二个参数,如果非null,则是指向写入线程函数的返回值或传递给pthread_exit()
的值的位置的指针。” >
无论如何,主要问题是我已经在注释中表达了什么:在您的连接循环中,您将覆盖pthread_create
提供的线程ID,并将您的任意值传递给pthread_join
。 这些不能识别您的线程,并且如果您的pthreads实现类似于我的线程,那么错误的线程ID实际上最终是无效的指针。您似乎不欣赏的是pthread_create
会生成并分配线程ID。这就是为什么您必须向其传递用于存储ID的地址的原因。因此,在将线程ID变量的地址传递给pthread_create
之前初始化线程ID变量是没有用的。
清理该问题并在valgrind下运行程序,再次表明您的线程函数中还有其他问题,如其他答案中所述。之所以发生这种情况,部分原因是您对pthread_create
的第四个参数与线程函数对其参数的用法不匹配。
pthread_create
的第四个参数直接传递给线程函数。您正在传递&argv[i]
,这是char *
(又称char **
)的地址,该地址会自动转换为void *
。您的线程函数将其参数直接传递给atoi()
,并自动转换为类型char *
。请注意char *
!= char **
。我认为您希望pthread_create
的第四个参数只是argv[i]
。至少它的类型符合您的用途。
也做了那个更正,我发现您的程序最终在pthread_join
循环内的无限循环中结束。我不确定为什么要在那儿循环-它似乎完全是免费的。
答案 1 :(得分:0)
您的代码有一个越界写错误。 A live test of your code
以下是错误消息。
==扩展DTS消息的开始==从此处复制开始==(56.127)==
运行时错误: [越界写入]
继续执行会导致不确定的行为,中止!
-
- Writing 4 bytes to 0x8fa0090 will corrupt the adjacent data.
-
- The object to-be-written (start:0x8fa0010, size:128 bytes) is allocated at
- file:/prog.c::10, 24
-
- 0x8fa0010 0x8fa008f
- +------------------------+
- |the object to-be-written|......
- +------------------------+
- ^~~~~~~~~~
- the write starts at 0x8fa0090 that is right after the object end.
-
- Stack trace (most recent call first) of the write.
- [1] file:/prog.c::18, 17
- [2] file:/musl-1.1.10/src/thread/pthread_create.c::168, 17
-
===扩展DTS消息的结尾====在此处复制结尾============