假设我要创建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
是&#34;你好&#34;而对于第二个,它是&#34; bye&#34;。稍后当我在线程1中打印字符串时,字符串是否会更改为&#34; bye&#34;而不是&#34;你好&#34;?
编辑:那么我应该为每个线程创建一个新的arg结构吗?
答案 0 :(得分:1)
此实施不安全。最后一个参数可能会在您没有注意到的情况下发生变化,因为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的代码
答案 1 :(得分:0)
您可以通过在创建线程之前和之后(从执行的线程内)打印参数的地址来检查这一点。如果地址相同,那么您只能传递指针。如果它们不同,那么除了错误之外,线程创建过程很可能将内存复制到不同的位置。
但是pthread_create()不仅会占用字符串。它可能需要任何空白*。那么它如何知道需要复制的数据类型有多大?
答案 2 :(得分:0)
假设“arg”是一个结构,并且arg.str是该结构中的字符字节数组,则在循环的每次迭代中都将覆盖arg.str的值。
每次调用pthread_create()时,都会传递指向同一结构arg的指针,因此每个线程都会有最后一个字符串的副本(在 last 迭代上传递给strncpy()你的for循环)...我认为这不是理想的行为。
答案 3 :(得分:0)
如果每次都将不同的字符串复制到同一个arg结构,则线程将全部看到字符串发生变化,因为您将相同的地址传递给每个线程。
您不能保证您复制的字符串是NUL终止的:
http://linux.die.net/man/3/strncpy
strncpy()函数类似,除了src的最多n个字节 被复制。警告:如果前n个字节中没有空字节 对于src,放在dest中的字符串不会以空值终止。
答案 4 :(得分:0)
是根据伪代码:
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的存储位置的任何值,即&amp; arg。 如果我们存储&#34;你好&#34;在arg中,所有线程都将打印&#34; hello&#34;。答案 5 :(得分:0)
除了M.先生注意到:
这完美地证明了我的话:http://hawk.guru/pthread_create-variable-copying/