如果保存副本并将其提供给另一个线程,为什么 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()