线程完成其工作后出现分段错误

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