代码分析
va_list 定义成指针
va_end 空定义
va_arg 取下一个变量地址
va_start 取的第一个参数后面参数的起始地址
#include <stdio.h>
#define va_list void *
#define va_end(arg)
#define va_arg(arg, type) *(type *)arg; arg = (char *)arg + sizeof(type)
#define va_start(arg, start) arg = (va_list)(((char *)&(start)) + sizeof(start))
int add(int nr, ...)
{
int i = 0;
int result = 0;
va_list arg = NULL;
va_start(arg, nr);
for(; i < nr; i++)
{
result += va_arg(arg, int);
}
va_end(arg);
return result;
}
int print(const char *format, ...)
{
va_list arg = NULL;
va_start(arg, format);
}
int main()
{
printf("%d", add(5, 1, 2, 3, 4, 5));
return 0;
}
X86系统中,调用栈中数据
参数N
参数N-1
参数N-2
......
参数1
EIP
EBP
临时变量N
其中EIP指向返回地址,也就是从该函数返回后应该执行的地址,通过这个地址可以知道是从哪个函数调用过来的。
EBP分割了当前函数和调用函数,EBP指向当前函数的栈顶。
参数从右到左压栈,所以这就解释了上面程序。
临时变量的分布有点诡异,以前分析过。有一些是最后变量在高地址,也有时候是在低地址。
理解这个了就知道backtrace是怎么实现的了。