我有一个while循环,它获取一个值并使用该信息调用新线程中的函数。问题是我无法让它在while循环的每次迭代中为我提供一个新地址。因此while循环最终会修改正在运行的线程使用的信息。
以下是我的代码的摘录。 printf语句显示字符串的地址相同,因此在线程运行时被覆盖
char * string = (char *) malloc(1024 * sizeof(char));
strcpy(string, item);
if (pthread_create(&thread, NULL, printWithDelay, &string)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
printf("Dispatched thread for %s at %p\n", string, &string);
free(string);
我也尝试过没有malloc,但也没有用。有没有办法做到这一点?
在你问之前,是的我是学生,是的,这是一项任务。但是,这项任务并未要求我做任何此事。我们甚至不应该知道线程存在。我只是想让自己超越任务的范围并且遇到一些麻烦。我正在尝试将睡眠作为对我个人认识的平地机的笑话。
此处的完整代码和作业说明:http://hastebin.com/cetepakevu.c
答案 0 :(得分:4)
根据您当前的pthread_create
来电,您有一个竞争条件,因为您正在传递&string
而不是string
(即您将指针传递给主要人员)线程的string
变量而不是内容)。因此,两个[或更多]子线程可能最终使用相同的字符串缓冲区。
此外,您有主线程在字符串上执行free
。这必须在子线程中完成。 free
全局适用于所有线程,因此在孩子可以使用数据之前free
为主[或者在此后不久将其从其自身下拉出来]。
此外,"未成年人"问题的结果是:因为main
执行malloc
和free
[假设没有子线程执行任何malloc
],所以很可能是malloc
将始终返回相同的值。因此,所有子线程可能使用相同的字符串缓冲区,竞争条件与否。
另一方面,如果一个子线程为其他东西做了malloc
,它现在正在反对使用string
[已经分配但已释放]和新分配。因此,持有/使用string
的先前值的人可能会导致堆损坏[和/或段错误]如果两个区域中的任何一个被写入"右"因为malloc/heap
链接指针可能位于重叠的不同分配的中间。
这是我认为你所拥有的[因为你没有展示儿童功能]:
void
main_thread(void)
{
while (1) {
char *string = (char *) malloc(1024 * sizeof(char));
strcpy(string, item);
// BUG: race condition -- on the second loop, string can be changed
// before thread 1 has a chance to dereference it, so thread 1
// could end up using thread 2's string (or thread 3's ...)
if (pthread_create(&thread, NULL, printWithDelay, &string)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
// BUG: child must do the free
printf("Dispatched thread for %s at %p\n", string, &string);
free(string);
}
}
void *
printWithDelay(void *arg)
{
char **strptr = arg;
char *string;
// BUG: this is the race condition -- we can get our string or
// if we're delayed, we'll get the string for the next thread, so
// we'd both use the same address
string = *strptr;
// use string ...
return (void *) 0;
}
以下是更正后的代码:
void
main_thread(void)
{
while (1) {
char *string = (char *) malloc(1024 * sizeof(char));
strcpy(string, item);
if (pthread_create(&thread, NULL, printWithDelay, string)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
}
}
void *
printWithDelay(void *arg)
{
char *string = arg;
// use string ...
free(string);
return (void *) 0;
}
答案 1 :(得分:0)
虽然pthread_create()
为void *
提供arg
,但您可以通过投放来传递值。我还没有对此进行验证,但这个答案似乎可以做你想要的。 pthread_create: Passing argument by value
我认为最好的方法是考虑使用不同的线程api(或语言),或者只是编写一个克隆函数并传递克隆变量的地址。