tags:

views:

288

answers:

2

"va_end - Macro to reset arg_ptr". After accessing a variable-argument list, the arg_ptr pointer is usually reset with va_end. I understand that it is required if you want to re-iterate the list, but is it really needed if you aren't going to? Is it just good practice, like 'always have default: in switch'?

Edit: Answered by greyfade, taking into account the comments

+11  A: 

va_end is used to do cleanup. You don't want to smash the stack, do you?

From man va_start:

va_end()

Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function. After the call va_end(ap) the variable ap is undefined. Multiple traversals of the list, each bracketed by va_start() and va_end() are possible. va_end() may be a macro or a function.

Note the presence of the word must.

greyfade
Does it mean that the pointer is 'global' and when the function is called a second time without resetting the pointer, the stack will become corrupted?
Yarik
It could become corrupted because *you don't know what va_start() is doing.* It could be doing anything. And it needs to be cleaned up. Therefore, when you call va_start(), you *MUST* match it with va_end().
greyfade
Thank you for the clarification.
Yarik
No one is really explaining the nitty gritty of a va_end() implementation, which is, I think, what the question was getting at.
Adam
the va_* macros are meant to be treated as black boxes. Every compiler on every platform can do whatever it wants there. It may do nothing, or it may do a lot. You don't know. That's my point.
greyfade
indeed. some ABIs pass first few args in registers, and remaining on the stack. a va_arg there may be more complicated. some are very easy.. you never know
Johannes Schaub - litb
Sure. You can look up how a given implementation does varargs, which may be interesting, but in writing portable code you treat them as atomic operations. Remember that sticking to the standard is safest, and in this case there's barely any penalty in doing so.
David Thornley
@Adam: it obviously depends on the platform. For many machines, it is a no-op. That means you can ignore the standard stricture about MUST use va_end() and you will mostly get away with it - but it is very foolish coding. Very foolish!
Jonathan Leffler
+5  A: 

In the common "parameters passed on the stack" implementation, I believe va_end() is usually nothing/empty/null. However, on platforms which have less traditional schemes, it becomes necessary. It's a "good practice" to include it to remain platform neutral.

James Curran