Как работает фрейм активации стека для функций с переменными аргументами?

#c

#c

Вопрос:

Я читаю http://www.cs.utexas.edu/users/lavender/courses/cs345/lectures/CS345-Lecture-07.pdf чтобы попытаться понять, как работает фрейм активации стека для функций с переменными аргументами?

В частности, как вызываемая функция может узнать, сколько аргументов передается?

На слайде говорилось: процедура va_start вычисляет значение fp offset после аргумента после последнего известного аргумента (например, формат const char). Затем остальные аргументы вычисляются путем вызова va_arg, где аргументом ‘ap’ для va_arg является некоторое значение fp offset .*

Мой вопрос в том, что такое fp (точка кадра)? как va_start вычисляет значения ‘fp offset’? и как va_arg получает ‘некоторые значения fp offset? и что va_end должен делать со стеком?

Ответ №1:

Функция не знает, сколько аргументов передается. По крайней мере, это не имеет значения, т. Е. В C вы не можете запрашивать количество аргументов.

Вот почему все функции varargs должны либо:

  • Используйте неизменяемый аргумент, который содержит информацию о количестве и типах всех переменных аргументов, например printf() does ; или
  • Используйте контрольное значение в конце списка переменных аргументов. Я не знаю функции в стандартной библиотеке, которая делает это, но см., Например gtk_list_store_set() , функцию GTK .

Оба механизма являются рискованными; если ваша printf() строка формата не соответствует аргументам, вы получите неопределенное поведение. Если бы был способ printf() узнать количество переданных аргументов, это, конечно, защитило бы от этого, но его нет. Так что это невозможно.

va_start() Макрос принимает в качестве аргумента последний неизменяемый аргумент, поэтому он может каким-то образом (это внутренние компоненты компилятора, нет единственно правильного или стандартного ответа, все, что мы можем сделать с этой стороны интерфейса, — это причина из доступных данных) использовать это, чтобы узнать, где находится первый изменяющийся аргументв стеке.

va_arg() Макрос получает тип в качестве «аргумента», что позволяет использовать его для вычисления смещения и, возможно, увеличения некоторого состояния в va_list объекте, чтобы указать на следующий изменяющийся аргумент.

Комментарии:

1. Не забудьте другой вопрос OP: fp = указатель на функцию и ap = указатель на аргумент.

2. @AustinMullins Нет, fp — это «указатель фрейма», как в «фрейме стека». Это было в вопросе.