代码之家  ›  专栏  ›  技术社区  ›  zell

使用pthread_create调用“int argc,char**argv->int”类型的c函数

  •  1
  • zell  · 技术社区  · 6 年前

    我需要使用pthread\u create来调用类型为

    int main_original(int argc, char** argv)
    

    我试过这样的方法:

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

    编译器给了我一个类型错误

    从–int(*)(int,char**)到–void的转换无效*( (无效) )

    那么,调用main_original以便其参数得到良好传递的正确方法是什么?

    1 回复  |  直到 6 年前
        1
  •  7
  •   Candy Gumdrop    6 年前

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

    void *fn(void *)
    

    即使您成功地将指针投射到具有不同签名的函数并将其成功传递给 创建线程 ,您的程序可能会崩溃 创建线程 将尝试以遵循平台调用约定的方式设置堆栈/寄存器,以便仅使用一个 void * 参数,这将导致函数处于不确定状态。

    解决问题的方法是使用专门为调用 创建线程 像这样:

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

    然而,这可能还不够,除非 argc argv 是全局变量。您可能会发现还需要以某种方式将这些值从调用的范围传递给此函数 void *arg 论证 创建线程 ,通过创建一个包含所需状态的结构,并通过casted 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. */
    }