n179911
n179911

Reputation: 20301

How does Stack Activation Frame for Variable arguments functions works?

I am reading http://www.cs.utexas.edu/users/lavender/courses/cs345/lectures/CS345-Lecture-07.pdf to try to understand how does Stack Activation Frame for Variable arguments functions works?

Specifically how can the called function knows how many arguments are being passed?

The slide said: The va_start procedure computes the fp+offset value following the argument past the last known argument (e.g., const char format). The rest of the arguments are then computed by calling va_arg, where the ‘ap’ argument to va_arg is some fp+offset value.*

My question is what is fp (frame point)? how does va_start computes the 'fp+offset' values? and how does va_arg get 'some fp+offset values? and what does va_end supposed to do with stack?

Upvotes: 2

Views: 221

Answers (1)

unwind
unwind

Reputation: 399833

The function doesn't know how many arguments are passed. At least not in any way that matters, i.e. in C you cannot query for the number of arguments.

That's why all varargs functions must either:

  • Use a non-varying argument that contains information about the number and types of all variable arguments, like printf() does; or
  • Use a sentinel value on the end of the variable argument list. I'm not aware of a function in the standard library that does this, but see for instance GTK+'s gtk_list_store_set() function.

Both mechanisms are risky; if your printf() format string doesn't match the arguments, you're going to get undefined behavior. If there was a way for printf() to know the number of passed arguments, it would of course protect against this, but there isn't. So it can't.

The va_start() macro takes as an argument the last non-varying argument, so it can somehow (this is compiler internals, there's no single correct or standard answer, all we can do from this side of the interface is reason from the available data) use that to know where the first varying argument is located on the stack.

The va_arg() macro gets the type as an "argument", which makes it possible to use that to compute the offset, and probably increment some state in the va_list object to point at the next varying argument.

Upvotes: 4

Related Questions