线程完成其工作后出现分段错误
Getting a segmentation fault after a thread completes it's job
#include <stdio.h>
#include <pthread.h>
void *print_n(int);
int main()
{
while (1)
{
pthread_t thread;
if (pthread_create(&thread, NULL, print_n(100), NULL))
{
printf("pthread_create error\n");
}
}
return 0;
}
void *print_n(int n)
{
printf("%d\n", n);
return NULL;
}
这是一个示例程序,旨在说明问题。第二次调用 pthread_create
后出现分段错误,但不知道为什么。
don't know why.
因为你的程序正在调用NULL
.
函数print_n(100)
returnsreturn NULL;
总是。所以:
pthread_create(&thread, NULL, print_n(100), NULL);
相当于:
print_n(100);
pthread_create(&thread, NULL, NULL, NULL);
这将启动一个调用 NULL
的单独线程。当此线程接收到处理器时间时,它会通过调用那里的函数来取消引用 NULL
。所以你的程序收到 segmentation fault
,因为它试图从受保护区域读取数据,在这种情况下取消引用 NULL
。
有趣的是,没有检查传递给 pthread_create
的函数是否为 NULL
。
问题是您对 pthread_create
的调用不是您所期望的。具体来说,第三个参数print_n(100)
是评估调用函数的结果,而不是传递一个指向创建线程要调用的函数的指针。因此,您会看到在计算函数时打印一次“100”,然后将其 return 值 NULL
传递给 pthread_create
,然后在启动线程时取消引用 NULL
段错误。所以实际上是 pthread_create
的第一次调用失败,而不是第二次调用。
另请注意,如果要将参数传递给函数,可以使用 pthread_create
的第 4 个参数来实现。这意味着当您想将 100 传递给新线程的函数时,您需要将 void*
传递给函数 print_n
然后需要适当处理的函数。并且该函数必须将 void*
作为参数,而不是像 int
这样的其他类型。
最后一件事要知道:在一个紧密的循环中创建如此多的线程,因为您已经耗尽了线程池资源(至少在我的平台上)return出现错误消息“资源暂时不可用”。您可以通过在 pthread_create
失败时检查 errno
来看到这一点。
这是我修改后的代码,以考虑到我所说的一切:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
void *print_n(void*);
int main()
{
int arg = 100;
while (1)
{
pthread_t thread;
if (pthread_create(&thread, NULL, print_n, &arg))
{
printf("pthread_create error: %s\n", strerror(errno));
}
}
return 0;
}
void *print_n(void *n)
{
int *arg = (int*)n;
printf("%d\n", *arg);
return NULL;
}
#include <stdio.h>
#include <pthread.h>
void *print_n(int);
int main()
{
while (1)
{
pthread_t thread;
if (pthread_create(&thread, NULL, print_n(100), NULL))
{
printf("pthread_create error\n");
}
}
return 0;
}
void *print_n(int n)
{
printf("%d\n", n);
return NULL;
}
这是一个示例程序,旨在说明问题。第二次调用 pthread_create
后出现分段错误,但不知道为什么。
don't know why.
因为你的程序正在调用NULL
.
函数print_n(100)
returnsreturn NULL;
总是。所以:
pthread_create(&thread, NULL, print_n(100), NULL);
相当于:
print_n(100);
pthread_create(&thread, NULL, NULL, NULL);
这将启动一个调用 NULL
的单独线程。当此线程接收到处理器时间时,它会通过调用那里的函数来取消引用 NULL
。所以你的程序收到 segmentation fault
,因为它试图从受保护区域读取数据,在这种情况下取消引用 NULL
。
有趣的是,没有检查传递给 pthread_create
的函数是否为 NULL
。
问题是您对 pthread_create
的调用不是您所期望的。具体来说,第三个参数print_n(100)
是评估调用函数的结果,而不是传递一个指向创建线程要调用的函数的指针。因此,您会看到在计算函数时打印一次“100”,然后将其 return 值 NULL
传递给 pthread_create
,然后在启动线程时取消引用 NULL
段错误。所以实际上是 pthread_create
的第一次调用失败,而不是第二次调用。
另请注意,如果要将参数传递给函数,可以使用 pthread_create
的第 4 个参数来实现。这意味着当您想将 100 传递给新线程的函数时,您需要将 void*
传递给函数 print_n
然后需要适当处理的函数。并且该函数必须将 void*
作为参数,而不是像 int
这样的其他类型。
最后一件事要知道:在一个紧密的循环中创建如此多的线程,因为您已经耗尽了线程池资源(至少在我的平台上)return出现错误消息“资源暂时不可用”。您可以通过在 pthread_create
失败时检查 errno
来看到这一点。
这是我修改后的代码,以考虑到我所说的一切:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
void *print_n(void*);
int main()
{
int arg = 100;
while (1)
{
pthread_t thread;
if (pthread_create(&thread, NULL, print_n, &arg))
{
printf("pthread_create error: %s\n", strerror(errno));
}
}
return 0;
}
void *print_n(void *n)
{
int *arg = (int*)n;
printf("%d\n", *arg);
return NULL;
}