pthread_create:分配(malloc)将整数作为最后一个参数传递的优势?

Posted

技术标签:

【中文标题】pthread_create:分配(malloc)将整数作为最后一个参数传递的优势?【英文标题】:pthread_create: advantages of allocate (malloc) for passing an integer as the last argument? 【发布时间】:2022-01-19 07:04:58 【问题描述】:

我发现了几个使用动态内存分配方法将整数作为最后一个参数传递的代码,比如这个例子:


void *foo(void *i) 
    int a = *((int *) i);
    free(i);


int main() 
    pthread_t thread;
    for ( int i = 0; i < 10; ++1 ) 
        int *arg = malloc(sizeof(*arg));
        if ( arg == NULL ) 
            fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
            exit(EXIT_FAILURE);
        

        *arg = i;
        pthread_create(&thread, 0, foo, arg);
    

    /*  Wait for threads, etc  */

    return 0;

否则,我找到了使用数组方法的学术示例,例如传递结构的示例:

//Runnable example
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct my_Struct
    int index;
    int value;
;
void* my_Func(void *received_struct)
    struct my_Struct *struct_ptr = (struct my_Struct*) received_struct;
    printf("index: %d  |  value: %d \n", struct_ptr->index, struct_ptr->value);
    //Now use 'struct_ptr->index', 'struct_ptr->value' as you wish

int main()
    struct my_Struct mystruct_1[5];
    
    printf("\nEnter 5 numbers:\n");
    for (int i=0; i<5; i++)
        scanf("%d", &mystruct_1[i].value);
        mystruct_1[i].index = i;
    
    pthread_t tid[5];
    for(int i=0; i<5; i++)
        pthread_create(&(tid[i]), NULL, my_Func, &mystruct_1[i]);
    
    for (int i=0; i<5; i++)    
        pthread_join(tid[i], NULL);
    

//To run: gcc [C FILE].c -lpthread -lrt
// ./a.out

//Grepper Profile: https://www.codegrepper.com/app/profile.php?id=9192

动态内存分配方式有什么好处?

更新:我在基于 gcc 的 IBM i 文档中发现他们使用 memory allocation

【问题讨论】:

你知道哪些区别?你怎么看? 有时需要分配。在这里你实际上没有。这与任何其他动态分配相同。如果你可以通过传递一个局部变量地址侥幸逃脱,那就去吧。 ... 或者,如果您可以通过传递文件范围变量的地址而侥幸逃脱,那么就去做吧。或者对于整数,通常只是将整数转换为指针并依靠线程函数将其转换回来。 C 标准不要求一个线程能够访问另一个线程的自动变量。 POSIX确实需要这个,但是为了完全的 C 可移植性(如果你想用 C11 线程替换 POSIX pthreads)你不能假设访问另一个线程的自动变量会起作用。 @UlrichEckhardt 我认为这可能与性能有关,或者在极少数情况下节省内存,但有人说数组方法的性能最好。 【参考方案1】:

pthread_create()的最后一个参数在新创建线程的栈上传递。当它是一个整数或任何其他大小小于或等于指针大小的值时,可以通过强制转换将参数原样传递给pthread_create()。但这不是推荐的方法,因为它在机器上不可移植,例如整数与指针的大小不同。让我们编译下面这个简单的程序:

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

void* thread_task(void* arg)

  printf("Thread received parameter: %d\n", (int)arg);
  return NULL;


int main(void)

  pthread_t tid;
  int i = 45;

  pthread_create(&tid, NULL, thread_task, (void *)i);

  pthread_join(tid, NULL);

  return 0;

gcc 编译器发出以下警告:

$ gcc pcreate.c -o pcreate -lpthread
pcreate.c: In function ‘thread_task’:
pcreate.c:6:45: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   printf("Thread received parameter: %d\n", (int)arg);
                                             ^
pcreate.c: In function ‘main’:
pcreate.c:15:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   pthread_create(&tid, NULL, thread_task, (void *)i);

因此,在结构或表条目或动态分配的内存区域上使用指针是使其可移植的方法。前面的程序可以固定为:

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

void* thread_task(void* arg)

  printf("Thread received parameter: %d\n", *((int *)arg));
  return NULL;


int main(void)

  pthread_t tid;
  int t[1] =  45 ;

  pthread_create(&tid, NULL, thread_task, (void *)t);

  pthread_join(tid, NULL);

  return 0;

编译器不再引发任何警告:

$ gcc pcreate.c -o pcreate -lpthread
$ ./pcreate
Thread received parameter: 45

【讨论】:

【参考方案2】:

当您只想传递一个整数时,您可以将其转换为指针:

void *foo(void *i) 
    int a = (int)i;


for ( int i = 0; i < 10; ++1 ) 
    pthread_create(&thread, 0, foo, (void*)i);

这提供了最大的效率,并且没有生命周期问题。

【讨论】:

以上是关于pthread_create:分配(malloc)将整数作为最后一个参数传递的优势?的主要内容,如果未能解决你的问题,请参考以下文章

pthread_create 中的错误参数

malloc分配内存为多大?

内存分配(malloc)的过程

malloc内存分配

iPhone应用程序中C代码的内存管理

利用中文数据跑Google开源项目word2vec