pthread_create 是否从指针复制参数值?

Does pthread_create copy the arguments value from the pointer?

假设我要创建 N 个线程,并且我将向每个线程传递不同的字符串。

伪代码:

for (i = 0; i < N; i++) {
   strncpy(arg.str, some_new_str, sizeof(arg.str));
   pthread_create(&threads[i],NULL,somefunc, (void *) &arg);
}

每个线程中arg指向的字符串会不会变化?比如说,对于创建的第一个线程,some_new_str 是 "hello",对于第二个线程,它是 "bye"。稍后当我在线程 1 中打印字符串时,字符串是否会更改为 "bye" 而不是 "hello"?

编辑:那么我应该为每个线程创建一个新的 arg 结构吗?

您可以通过在线程创建之前和之后(从已执行的线程中)打印参数的地址来简单地检查这一点。如果地址相同,那么您 传递指针。如果它们不同,那么除了错误之外,线程创建过程可能会将内存复制到不同的位置。

但是 pthread_create() 不仅仅接受字符串。它可以采用任何 void*。那么它如何知道需要复制的数据类型有多大?

这个实现不安全。最后一个参数可能会在您不注意的情况下发生变化,因为 pthread_create 不会立即创建线程。它会在某个时候执行,但到那时您的本地 arg 可能已经更改。

举个例子,试试运行这个代码:

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

void* worker(void *arg) {
  int val = *((int*)arg);
  printf("% 5d", val);
  return arg;
}

int main() {
  pthread_t thid;
  pthread_attr_t attr;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int n = 200;
    int x = 0;
    for(x = 0; x < n; ++x) {
      pthread_create(&thid, &attr, worker, &x);
    }
  sleep(2);
  printf("\n========\n");
}

看看会发生什么。

代码由 P. Czarnik

假设 "arg" 是一个结构,而 arg.str 是该结构中的字符字节数组,您将在循环的每次迭代中覆盖 arg.str 的值。
您正在为每次调用 pthread_create() 传递一个指向相同结构 arg 的指针,因此每个线程都将拥有最后一个字符串的副本(在 上传递给 strncpy()最后 for循环的迭代)...我认为这不是所需的行为。

  1. 如果您每次都将不同的字符串复制到相同的 arg 结构中,则所有线程都会看到字符串发生变化,因为您将相同的地址传递给每个线程。

  2. 您不能保证您复制的字符串以 NUL 结尾:

http://linux.die.net/man/3/strncpy

The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.

是 根据伪代码:

    for(i = 0; i < N; i++) {
   strncpy(arg.str, some_new_str, sizeof(arg.str));
   pthread_create(&threads[i],NULL,somefunc, (void *) &arg);
}

在使用 pthread_create 创建线程时,我们正在传递 arg 的地址。 由于 pthread_create 的参数传递部分作为指针传递。

因此所有线程都将打印存储在 arg 内存位置的任何值,即 &arg。 如果我们将 "hello" 存储在 arg 中,那么所有线程都将打印 "hello".

除了 M 先生注意到:

  1. 不,arg 结构不会被 pthread_create 函数复制,因为函数根本不知道你给它的参数的大小。
  2. 所以,是的,您应该为每个对 pthread_create 的调用创建不同的结构。

这完美地证明了我的话:http://hawk.guru/pthread_create-variable-copying/