变量参数函数的堆栈激活框架如何工作?

时间:2014-06-26 06:40:53

标签: c

我正在阅读http://www.cs.utexas.edu/users/lavender/courses/cs345/lectures/CS345-Lecture-07.pdf以试图了解Stack Activation Frame for Variable参数函数是如何工作的?

具体来说,被调用函数如何知道传递了多少个参数?

幻灯片说: va_start过程计算参数后面的fp +偏移值 超过最后一个已知参数(例如,const char 格式)。然后通过调用计算其余参数 va_arg,其中va_arg的'ap'参数是一些fp +偏移值。*

我的问题是什么是fp(帧点)? va_start如何计算' fp + offset'值? 以及va_arg如何得到一些fp +偏移值?以及va_end应该如何处理堆栈?

1 个答案:

答案 0 :(得分:4)

该函数不知道传递了多少个参数。至少不以任何方式重要,即在C中你不能查询参数的数量。

这就是为什么所有varargs函数都必须:

  • 使用包含所有变量参数的数量和类型信息的非变量参数,例如printf();或
  • 在变量参数列表的末尾使用sentinel值。我不知道标准库中有哪个函数可以执行此操作,但请参阅GTK +的gtk_list_store_set()函数。

这两种机制都存在风险;如果您的printf()格式字符串与参数不匹配,您将获得未定义的行为。如果printf()有一种方法可以知道传递的参数的数量,那么它当然可以防止这种情况,但是没有。所以它不能。

va_start()宏将最后一个非变量参数作为参数,因此它可以某种方式(这是编译器内部,没有单一的正确或标准答案,我们可以从界面的这一侧做的所有事情是来自可用数据的原因)使用它来知道第一个变化参数在堆栈中的位置。

va_arg()宏将类型作为“参数”获取,这使得可以使用它来计算偏移量,并可能增加va_list对象中的某个状态以指向下一个变化参数。