任何人都有参考x86_64 ABI(Linux上使用的那个)中va_list
的表示?我正在尝试调试一些代码,其中堆栈或参数似乎已损坏,这将真正有助于理解我应该看到的内容......
答案 0 :(得分:28)
我对答案做了评论。
This may help。这是一个参考,尽管是轻量级的(编辑:原始链接已死;替换了Wayback Machine保留的链接)。
变量参数列表参考从第50页开始,然后继续,第52-53页文档va_list
:
va_list类型
va_list类型是一个数组 包含一个元素 结构包含必要的 实现va_arg的信息 宏。 va_list的定义 类型在图3.34中给出
// Figure 3.34
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} va_list[1];
va_start宏
va_start宏初始化 结构如下:
reg_save_area
元素指向 寄存器保存区的开始。
overflow_arg_area
使用此指针 获取传递的参数 堆。它初始化为 传递的第一个参数的地址 堆栈,如果有的话,然后总是 更新以指向开始 堆栈上的下一个参数。
gp_offset
元素保留偏移量 从reg_save_area到。的字节数 下一个可用的将军的地方 目的参数寄存器已保存。在 case所有参数寄存器都是 用尽,它被设置为值48 (6 * 8)。
fp_offset
元素保留偏移量 从reg_save_area到。的字节数 下一个可用浮动的地方 点参数寄存器已保存。在 case所有参数寄存器都是 耗尽,将其设置为值304 (6 * 8 + 16 * 16)。
答案 1 :(得分:14)
事实证明问题是gcc使va_list
成为数组类型。我的功能是签名:
void foo(va_list ap);
我希望将指向ap
的指针传递给另一个函数,所以我做了:
void foo(va_list ap)
{
bar(&ap);
}
不幸的是,数组类型衰减到函数参数列表中的指针类型,所以我没有将指针传递给原始结构,而是将指针传递给指针。
要解决此问题,我将代码更改为:
void foo(va_list ap)
{
va_list ap2;
va_copy(ap2, ap);
bar(&ap2);
va_end(ap2);
}
这是我能提出的唯一可移植解决方案,它解释了va_list
是数组类型的可能性以及它不是的可能性。
答案 2 :(得分:0)
在i386体系结构中,va_list是指针类型。但是,在AMD64体系结构中,它是一种数组类型。有什么区别?实际上,如果将&操作应用于指针类型,则将获得此指针变量的地址。但是,无论您对数组类型应用和操作多少次,其值都是相同的,并且等于该数组的地址。
那么,您应该在AMD64中做什么?在函数中传递va_list变量的最简单方法是不带*或&运算符来传递它。
例如:
void foo(const char *fmt, ...) {
va_list ap;
int cnt;
va_start(ap, fmt);
bar(fmt, ap);
va_end(ap);
return cnt;
}
void bar(const char *fmt, va_list ap) {
va_arg(ap, int);
//do something
test(ap);
}
void test(va_list ap) {
va_arg(ap, int);
//do something
}
就可以了!而且您不必担心有多少论点。