c - 使用 pthread_create 调用类型为 "int argc, char** argv -> int"的 C 函数

标签 c pthreads

我需要使用 pthread_create 来调用类型的 C 函数

int main_original(int argc, char** argv)

我试过这样的:

pthread_create(&t, NULL, main_original, NULL);

编译器给我一个类型错误

invalid conversion from ‘int (*)(int, char**)’ to ‘void* ()(void)’

那么,调用 main_original 的正确方法是什么,以便它的参数能够很好地传递?

最佳答案

函数 pthread_create 只能调用具有以下签名的函数:

void *fn(void *)

即使您设法将指针转换为具有不同签名的函数并成功将其传递给 pthread_create,您的程序也可能会崩溃,因为 pthread_create 将尝试以一种遵循平台对仅具有一个 void * 参数的函数的调用约定的方式设置堆栈/寄存器,这将导致您的函数处于不确定状态。

解决您的问题的方法是使用专门为被 pthread_create 调用而设计的包装函数,如下所示:

void *main_original_start_routine(void *arg)
{
    main_original(argc, argv);
    return NULL;
}

但是,这可能还不够,除非argcargv 是全局变量。您可能会发现您还需要以某种方式将这些值从您调用 pthread_create 的范围传递给此函数。这可以通过 pthread_createvoid *arg 参数来完成,方法是创建一个包含您需要的状态的结构,并通过转换的 void 指针传递它:

struct main_original_context {
    int argc;
    char **argv;
};

void *main_original_start_routine(void *arg)
{
    /* Convert the void pointer back to the struct pointer it
     * really is. */
    struct main_original_context *ctx = arg;
    main_original(ctx->argc, ctx->argv);
    return NULL;
}

int main(int argc, char **argv)
{
    pthread_t t;

    struct main_original_context ctx = {
        argc,
        argv
    };

    /* Pass a pointer to our context struct to the thread routine. */
    pthread_create(&t, NULL, &main_original_start_routine, &ctx);

    pthread_join(&t, NULL);

    return 0;
}

但是请记住,在这种情况下,ctx 的生命周期只有 main 函数的持续时间。如果我们在其中创建 pthread 的函数在返回之前没有加入 pthread_join(并使用于为线程提供上下文的结构无效),那么这将是不安全的。因此我们必须使用动态分配,并让线程负责释放任何动态分配的内存:

struct main_original_context {
    int foo;
    int bar;
};

void *foobar_start_routine(void *arg)
{
    struct main_original_context *ctx = arg;
    foobar(ctx->foo, ctx->bar);

    /* Free memory we have been given responsibility for. */
    free(ctx);

    return NULL;
}

void asdf(int foo, int bar)
{
    pthread_t t;

    struct main_original_context *ctx;

    /* Allocate memory. */
    ctx = malloc(sizeof *ctx);

    ctx->foo = foo;
    ctx->bar = bar;

    /* Assume `main_original_start_routine` is now responsible for freeing
     * `ctx`. */
    pthread_create(&t, NULL, &foobar_start_routine, ctx);

    /* Now we can safely leave this scope without `ctx` being lost.  In
     * the real world, `t` should still be joined somewhere, or
     * explicitly created as a "detached" thread. */
}

关于c - 使用 pthread_create 调用类型为 "int argc, char** argv -> int"的 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50703913/

相关文章:

c - 为什么 pthread_join 在最后一次迭代中失败(给出段错误)?

c - Fortran调用DLL Visual Studio 2010

c - 选项卡中的元素 WinAPI

C 从字符串中删除多个字母

c - main 之前的段错误

c - 如何在 C 中扩展二维动态数组?

c - 如何设置特定 pthread 的 CPU 关联性?

GCC:为 ARM 构建交叉编译器 - 未找到 pthread.h

c++ - 是否可以在不使用 SIGHUP 的情况下立即启动 pthread?

c++ - 我是否过度设计了每线程信号阻塞?