【问题标题】:Passin a pointer to a pthread function result in losing his structure将指针传递给 pthread 函数会导致其结构丢失
【发布时间】:2015-10-26 07:38:42
【问题描述】:

我正在尝试启动一个线程并给他一个指向结构的指针。但是函数接收到的指针不正确。我有一部分结构正确,但其他结构不正确。

这是启动线程的函数:

void start_pointer(struct fsm_pointer *pointer) {
    if ( pointer->started != 0 ){
        printf("CRITICAL : A pointer must be started only once");
        return;
    }
    pthread_create(&pointer->thread, NULL, &pointer_loop, (void *)pointer);
    pointer->started = 1;
}

这里是pointer_loop 函数:

void *pointer_loop(void * _pointer) {
    struct fsm_pointer * pointer = _pointer; // cast void pointer
    struct fsm_context init_context = {
        .event = event,
        .fnct_args = step.args,
    };
    // call pointer structure member => SEGFAULT
    pointer->current_step.fnct(&init_context); 
    return NULL;
}

结构定义如下:

struct fsm_pointer{
    pthread_t thread;
    pthread_mutex_t mutex_event;
    pthread_cond_t cond_event;
    struct fsm_event input_event;
    struct fsm_step current_step;
    unsigned short started;
};

struct fsm_step{
    void (*fnct)(const struct fsm_context *);
    void * args;
    struct fsm_trans transition;
};

::编辑::
这就是pointerstep 结构的生命力:

struct fsm_pointer * create_pointer(struct fsm_step first_step)
{
    struct fsm_pointer *pointer = malloc(sizeof(pointer));
    pointer->thread = 0;
    pointer->mutex_event = PTHREAD_MUTEX_INITIALIZER;
    pointer->cond_event = PTHREAD_COND_INITIALIZER;
    pointer->input_event = _NONE_EVENT;
    pointer->current_step = first_step;
    pointer->started = 0;
    return pointer;
}

struct fsm_step create_step(void (*fnct)(const struct fsm_context *), void *args)
{
    struct fsm_step result = {
            .fnct = fnct,
            .args = args,
            .transition = TRANS_ENDPOINT,
    };
    return result;
}

这是管理它的功能:

void test_new_fsm(){
    struct fsm_step step_0 = create_step(&callback, NULL);
    struct fsm_pointer *fsm = create_pointer(step_0);

    start_pointer(fsm);
    sleep(5);
    pthread_join(fsm->thread, NULL);
    sleep(1);
    free(fsm);
}

而且回调函数只是为了测试:

void callback(const struct fsm_context *context) {
    printf("Callback : event uid : %d \n", context->event.uid);
}

::/EDIT::

当我在段错误之前使用调试器 (gdb) 时,我可以看到指针的地址是正确的(与创建线程之前相同)并且 started 变量正确设置为 1。但 @987654332 @pointer 是 NULL 会产生段错误。

如果在创建线程之前执行与指针循环中完全相同的代码(具有正确的变量名),则没有任何问题。

那么,是否有人知道发生了什么,或者这只是一个明显的错误,如此明显以至于超过一天的调试还不够?

谢谢。

【问题讨论】:

  • 你怎么称呼start_pointer?您可以尝试创建一个Minimal, Complete, and Verifiable Example 并展示给我们吗?
  • fcnt 在哪里/如何设置?您确实需要按照建议创建一个 MCVE。问题很可能不在您显示的代码中(例如,您可能有一个竞争条件,其中fcnt 在线程执行之前被设置为 NULL。)
  • 当然,我原以为可能是代码太多,并试图显示最少,但缺少重要部分。我已经和他们一起编辑了我的帖子。

标签: c multithreading pointers segmentation-fault pthreads


【解决方案1】:
struct fsm_pointer *pointer = malloc(sizeof(pointer));

应该是:

struct fsm_pointer *pointer = malloc(sizeof(struct fsm_pointer));

struct fsm_pointer *pointer = malloc(sizeof(*pointer));

【讨论】:

【解决方案2】:

您还没有显示pointer 指向的类型为struct fsm_pointer 的对象存在的代码,但推测它正在被修改,或者它的生命周期即将结束,而没有与新创建的线程的访问同步它。除非您在线程启动函数和调用者中进行同步以排除并发访问/生命周期结束,否则您将不得不等到您加入线程以释放此结构或以其他方式允许其生命周期结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2019-05-03
    相关资源
    最近更新 更多