This blog post sostiene che il superamento di un va_list
a un'altra funzione, come nel codice seguente è a rischio, e che la va_list
deve prima essere copiati usando va_copy
:È sicuro passare una va_list a un'altra funzione senza usare va_copy?
void
foo_ap(const char *fmt, va_list ap)
{
char buf[128];
vsnprintf(buf, sizeof(buf), fmt, ap);
// now, do something with buf ...
}
Come uno dei commenti al post del blog cita, posso vediamo come questo non sarebbe sicuro, come afferma la specifica C99 (7.15):
L'oggetto
ap
può essere passato come argomento ad un'altra funzione; se tale funzione richiama la macrova_arg
con il parametroap
, il valore diap
nella funzione di chiamata è indeterminato e deve essere passato alla macrova_end
prima di qualsiasi ulteriore riferimento aap
.
(Finché foo_ap
non fa riferimento ap
dopo aver passato su, la seconda parte della frase non sembra applicarsi in ogni caso.) L'autore del post dice in un altro commento che potrebbe essere sbagliato, ma forse qualcuno può aggiungere qualche chiarimento. Devo davvero usare va_copy
per essere al sicuro? O ci sono piattaforme che non sono conformi alle specifiche e richiedono l'uso di va_copy
?
Il post del blog sembra contraddire direttamente la clausola citata dallo standard C99. L'autore del blog dice "Molto tempo fa" all'inizio, quindi la mia ipotesi è che avesse a che fare con un vecchio sistema non conforme agli standard. –
È necessario solo 'va_copy' se si prevede di utilizzare' ap' dopo il ritorno di 'vsnprintf'. Ad esempio, potresti voler chiamare 'vsnprintf' due volte - una volta per determinare la dimensione del buffer richiesta, e di nuovo per formattare per reale. Se non hai più bisogno di usare 'ap' di nuovo eccetto per il suo passaggio a' va_end', non devi necessariamente 'va_copy' it. –
@IgorTandetnik Se si rende il commento una risposta, lo accetterò. – nwellnhof