如果副本被保存并提供给另一个线程,为什么va_list var-arg副本不能按预期工作?

问题描述 投票:0回答:1

在这个例子中,如果我直接从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
c pthreads variadic-macros
1个回答
2
投票

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_startva_copy宏的每次调用都应与相同函数中va_end宏的相应调用相匹配。

因此,print_mydb()表现出未定义的行为,因为它在va_end()返回之前不会调用vobj

© www.soinside.com 2019 - 2024. All rights reserved.