【问题标题】:pthread_create argument is lostpthread_create 参数丢失
【发布时间】:2017-01-20 15:04:17
【问题描述】:

我正在编写一个非常简单的代码,其中需要使用一些线程。 当我创建第一种类型的线程时,我使用 pthread_create 传递参数:

 fman thread_arg;
 thread_arg.sd=sda;
 char* split = strtok(buffer, "|");
 thread_arg.wcount=atoi(split);
 split = strtok(NULL,"");
 strcpy(thread_arg.id, split);
 pthread_create(&thread_temp, NULL, registerF, &thread_arg);

一切正常,但在函数 registerF 中我需要做这样的事情:

wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);

这些参数是我定义的结构:

typedef struct fman
{
    int sd;
    char id[100];
    int wcount;
} fman;

typedef struct wman
{
    int sd;
    int fmanix;
    char id[100];
} wman;

当我通过 printf("%x, args) 检查它时,我得到相同的地址,但里面的值不同。我的错误在哪里?

【问题讨论】:

    标签: c linux multithreading


    【解决方案1】:

    这里有一个可能的问题:

     fman thread_arg;
     [...]
     pthread_create(&thread_temp, NULL, registerF, &thread_arg);
    

    请注意,thread_arg 对象位于堆栈上,因此在声明它的函数返回时将被销毁(并可能被其他堆栈变量覆盖)。

    另一方面,

    pthread_create() 会启动一个线程,该线程将与此函数异步运行,这意味着该线程可以(并且通常会)在您摘录的函数返回之后运行,这意味着当线程取消引用 &thread_arg 时,thread_arg 可能已经被销毁,并且该指针现在指向稍后写入同一堆栈位置的其他一些数据。

    除非您正在做一些特殊的事情来确保结构的生命周期足够长以包含所有衍生线程对结构的访问,否则此代码能够正常工作的事实纯属运气(即调度程序恰好安排了在结构被销毁/覆盖之前运行并执行对结构的所有访问的线程)。你绝对不能依赖它。

    为了解决这个问题,你需要在堆上分配结构(这样它就不会在函数返回时被破坏——生成的线程可以在使用完结构后释放它) , 或使用某种同步机制(例如条件变量)使主线程在您的函数内部阻塞,直到生成的线程表明它已完成对结构的访问。

    【讨论】:

    • 这真的很有帮助。谢谢你。 :)
    【解决方案2】:

    正在运行的线程中的线程结构被视为一块内存并使用偏移量进行访问。由于您的 fman 和 wman 结构具有不同的顺序 (4+100+4) 与 (4+4+100),因此您可能得到了正确的结构,但从不同的内存位置读取,因为传递给该线程的结构是 fman ,并且它被作为 wman 访问。

    尝试将它们都更改为相同的签名,如 in、int、int、char*,它应该可以工作。

    【讨论】:

    • 还是什么都没有。我将源代码更改为在 main 和 registerF 线程中使用 fman 结构,但它仍然不起作用。
    • 你能不能把完整的代码,一个最小的例子?
    猜你喜欢
    • 2017-02-23
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 2018-05-12
    • 2013-10-22
    相关资源
    最近更新 更多