va_end
est utilisé pour effectuer le nettoyage. Vous ne voulez pas casser la pile, n'est-ce pas?
De man va_start
:
va_end()
chaque invocation de va_start() doit être accompagnée d'une invocation correspondante de va_end() dans la même fonction. Après l'appel va_end (ap) la variable ap est indéfinie. Plusieurs traversées de la liste, chacune encadrée par va_start() et va_end() sont possibles. va_end() peut être une macro ou une fonction.
Notez la présence du mot doit.
La pile peut être corrompue car vous ne savez pas ce que va_start()
fait. Les macros va_*
sont censées être traitées comme des boîtes noires. Chaque compilateur sur chaque plate-forme peut faire ce qu'il veut là-bas. Cela peut ne rien faire ou faire beaucoup.
Certains ABI transmettent les premiers arguments dans les registres et le reste dans la pile. Un va_arg()
il peut y avoir plus compliqué. Vous pouvez rechercher comment une implémentation donnée fait varargs, ce qui peut être intéressant, mais en écrivant du code portable, vous devriez les traiter comme des opérations opaques.
C'est une très bonne question. Je souhaite que quelqu'un y réponde en décrivant une architecture où va_end n'est pas un no-op. – erikkallen
FYI: MSVS2008 - #define _crt_va_end (ap) (ap = (va_list) 0) – Yarik
@erikkallen: Faire une recherche google pour "define va_end" et vous trouverez quelques définitions inhabituelles qui peuvent ou non être essentiellement un op. – PlasmaHH