In this Q&A it is established that you should always call va_end()
:
What exactly is va_end for? Is it always necessary to call it?
But what if a piece of code longjmp's before you reach the va_end? Is there any promise on va_end's part that it will be okay? Or conceptually might it (for example) do a memory allocation in va_start()
that would be leaked, vs. just using stack tricks?
The C99 rationale explicitly states that va_start
may allocate memory that ends up freed by va_end
, exactly what you guessed in your question:
7.15.1.2 The
va_copy
macro[...]
30 A much simpler approach is to copy the
va_list
object used to represent processing of the arguments. However, there is no safe way to do this in C89 because the object may include pointers to memory allocated by theva_start
macro and destroyed by theva_end
macro.
The newva_copy
macro provides this safe mechanism.[...]
So yes, you need to invoke va_end
before a longjmp
. At the very least you'd otherwise have a memory leak on such an implementation.
Supposedly Pyramid OSx had an implementation where memory allocations were performed by va_start
. Function arguments were passed in registers. This was the case even for variadic functions. It may have pre-dated ANSI C's invention of function prototypes, meaning the caller wouldn't know whether it was dealing with a variadic function. va_start
allocated memory, presumably to store the function parameter values in a way that va_arg
could easily access it. va_end
freed the allocated memory.
Its implementation of va_start
and va_end
actually required matching va_start
and va_end
syntactically, because it was one that used unbalanced braces, so ANSI C already disallowed that implementation, but the same principle could be made to work while having matching braces.
I can find very little concrete information on this implementation, it's just bits and pieces on Usenet in the late '80s, early '90s. What little I did find may be incomplete or even just plain wrong. More details are very welcome, especially by anyone who used this implementation themselves.