函数的多个参数由pthread_create()调用?

时间:2009-08-30 00:52:58

标签: c pthreads

我需要将多个参数传递给我想在单独的线程上调用的函数。我read这样做的典型方法是定义一个结构,向该函数传递指向该结构的指针,并为参数取消引用它。但是,我无法让这个工作:

#include <stdio.h>
#include <pthread.h>

struct arg_struct {
    int arg1;
    int arg2;
};

void *print_the_arguments(void *arguments)
{
    struct arg_struct *args = (struct arg_struct *)args;
    printf("%d\n", args -> arg1);
    printf("%d\n", args -> arg2);
    pthread_exit(NULL);
    return NULL;
}

int main()
{
    pthread_t some_thread;
    struct arg_struct args;
    args.arg1 = 5;
    args.arg2 = 7;

    if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
        printf("Uh-oh!\n");
        return -1;
    }

    return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

此输出应为:

5
7

但是当我运行它时,我实际上得到了:

141921115
-1947974263

任何人都知道我做错了什么?

9 个答案:

答案 0 :(得分:65)

因为你说

struct arg_struct *args = (struct arg_struct *)args;

而不是

struct arg_struct *args = arguments;

答案 1 :(得分:16)

使用

struct arg_struct *args = (struct arg_struct *)arguments;

取代

struct arg_struct *args = (struct arg_struct *)args;

答案 2 :(得分:4)

main()拥有自己的线程和堆栈变量。要么为堆中的'args'分配内存,要么将其设为全局:

struct arg_struct {
    int arg1;
    int arg2;
}args;

//declares args as global out of main()

然后当然会将引用从args->arg1更改为args.arg1等等。

答案 3 :(得分:2)

使用:

struct arg_struct *args = malloc(sizeof(struct arg_struct));

并传递这样的论点:

pthread_create(&tr, NULL, print_the_arguments, (void *)args);

别忘了免费的args! ;)

答案 4 :(得分:1)

struct arg_struct *args = (struct arg_struct *)args;

->这种分配是错误的,我的意思是在这种情况下应该使用变量参数。 干杯!!!

答案 5 :(得分:1)

在此代码的线程创建中,正在传递函数指针的地址。 原本的 pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

它应该读为 pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

记住的一个好方法是该函数的所有参数都应该是地址。

some_thread是静态声明的,因此使用&可以正确发送地址。

我将创建一个pthread_attr_t变量,然后在其上使用pthread_attr_init()并传递该变量的地址。但是,传递NULL指针也是有效的。

导致此问题的原因是功能标签前面的&。使用的标签已经是函数的void*,因此仅需要标签。

用最后一个论点说!= 0似乎会引起不确定的行为。添加此表示已传递布尔值而不是引用。

Akash Agrawal的答案也是该代码问题解决方案的一部分。

答案 6 :(得分:1)

我和原始海报的迈克尔有同样的问题。

但是我尝试将针对原始代码提交的答案应用于成功

经过反复试验,这是我可以使用的代码版本(或至少对我有用!)。如果仔细观察,您会注意到它与先前发布的解决方案不同。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct arg_struct
{
   int arg1;
   int arg2;
} *args;

void *print_the_arguments(void *arguments)
{
   struct arg_struct *args = arguments;
   printf("Thread\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   pthread_exit(NULL);
   return NULL;
}

int main()
{
   pthread_t some_thread;
   args = malloc(sizeof(struct arg_struct) * 1);

   args->arg1 = 5;
   args->arg2 = 7;

   printf("Before\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   printf("\n");


   if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
   {
      printf("Uh-oh!\n");
      return -1;
   }

   return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

答案 7 :(得分:0)

print_the_arguments的参数是参数,因此您应该使用:

struct arg_struct *args = (struct arg_struct *)arguments. 

答案 8 :(得分:0)

Solaris sigaction()起,我不妨提供C ++代码作为答案。

volatile sig_atomic_t running;

void handler( int sig );
{
    running = 0;
}
...

struct sigaction sa;
memset( &sa, 0, sizeof( sa ) );
sa.sa_handler = handler;

sigaction( SIGALRM, &sa, NULL );
while(running)
{
    // 10-sec timeout
    alarm( 10 );

    errno = 0;
    ssize_t result = msgrcv( msqid, &req_msg, sizeof(req_msg.mtext), 0, 0 );
    
    // save errno as alarm() can munge it
    int saved_errno = errno;

    // clear alarm if it hasn't fired yet
    alarm( 0 );

    if ( result == ( ssize_t ) -1 )
    {
        // if the call failed or no longer running
        // break the loop
        if ( ( saved_errno != EINTR ) || !running )
        {
            break;
        }

        // the call was interrupted by a signal
        continue
    }

    ...
}

使用以下方法之一进行编译和运行:

insert into destinationsever.destinationdatabase.dbo.destinationtable
select * from sourcesever.sourcedatabase.dbo.sourcetable