如果副本被保存并提供给另一个线程,为什么va_list var-arg副本不能按预期工作?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果副本被保存并提供给另一个线程,为什么va_list var-arg副本不能按预期工作?相关的知识,希望对你有一定的参考价值。
在这个例子中,如果我直接从main调用tsub,则输出是预期的。如果为tsub启用了pthread模式,则不会给出预期的输出。
va_list vobj;
void *tsub (void *arg)
{
printf ("vobj: %d, %f\n", va_arg (vobj, int), va_arg (vobj, double));
return NULL;
}
void print_mydb (char *name, ...)
{
va_list ap;
va_start (ap, name);
va_copy (vobj, ap);
va_end (ap);
}
int main (void)
{
pthread_t tid;
print_mydb ("b10", 6, 5.23);
#if 1
printf ("THREADY!!!!!\n");
pthread_create (&tid, NULL, tsub, (void *)vobj);
pthread_join (tid, NULL);
#else
tsub (NULL);
#endif
return 0;
}
直接tsub调用的输出:
vobj: 6, 5.230000
tsub的pthread调用输出:
THREADY!!!!!
vobj: 0, 0.000000
答案
AFAICS,你两次都在调用未定义的行为;它只是有时工作(似乎在这种情况下工作),有时不工作。当print_mydb()
返回时,复制的vobj
指向无效数据 - 提供它指向的数据(参数列表)的函数调用已返回,因此vobj
的内容现在没有意义。无论你是直接调用tsub()
还是通过pthread_create()
调用,你都会在传递给print_mydb()
后滥用记忆。当pthread_create()
在记忆中被践踏时,它会变得更糟。
此外,调用va_copy()
的函数必须在复制列表返回之前调用va_end()
。 C11 §7.16.1 Variable argument list access macros ¶1
va_start
和va_copy
宏的每次调用都应与相同函数中va_end
宏的相应调用相匹配。
因此,print_mydb()
表现出未定义的行为,因为它在va_end()
返回之前不会调用vobj
。
以上是关于如果副本被保存并提供给另一个线程,为什么va_list var-arg副本不能按预期工作?的主要内容,如果未能解决你的问题,请参考以下文章
提示文件打开,进行更改并另存为另一个副本,然后关闭+取消保存原始文件