如果保存副本并将其提供给另一个线程,为什么 va_list var-arg 副本无法按预期工作?
Why does va_list var-arg copy not work as expected if the copy is saved and given to another thread?
如本例所示,如果我直接从 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()
returns 时,复制的 vobj
指向无效数据 — 提供其指向的数据(参数列表)的函数调用已返回,因此 [=11= 的内容] 现在毫无意义。无论您是直接调用 tsub()
还是通过 pthread_create()
调用都没有关系,一旦传递给 print_mydb()
,您就是在滥用内存。当 pthread_create()
在调用时践踏内存时,情况会更糟。
此外,调用 va_copy()
的函数必须 在它之前的复制列表上调用 va_end()
returns。 C11 §7.16.1 Variable argument list access macros ¶1
Each invocation of the va_start
and va_copy
macros
shall be matched by a corresponding invocation of the va_end
macro in the same
function.
因此,print_mydb()
表现出未定义的行为,因为它没有在 returns.
之前的 vobj
上调用 va_end()
如本例所示,如果我直接从 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()
returns 时,复制的 vobj
指向无效数据 — 提供其指向的数据(参数列表)的函数调用已返回,因此 [=11= 的内容] 现在毫无意义。无论您是直接调用 tsub()
还是通过 pthread_create()
调用都没有关系,一旦传递给 print_mydb()
,您就是在滥用内存。当 pthread_create()
在调用时践踏内存时,情况会更糟。
此外,调用 va_copy()
的函数必须 在它之前的复制列表上调用 va_end()
returns。 C11 §7.16.1 Variable argument list access macros ¶1
Each invocation of the
va_start
andva_copy
macros shall be matched by a corresponding invocation of theva_end
macro in the same function.
因此,print_mydb()
表现出未定义的行为,因为它没有在 returns.
vobj
上调用 va_end()