首页>Program>source

任何人都可以参考 va_list 在x86_64 ABI(Linux上使用的那个)中? 我正在尝试调试一些堆栈或参数似乎已损坏的代码,这确实有助于理解我应该所见...

最新回答
  • 2021-1-12
    1 #

    我将自己的评论写成了答案。

    这可能会有所帮助.这是参考,尽管是轻量级的( EDIT :原始链接已失效; 替换了wayback Machine保留的链接)。

    可变参数列表参考从第50页开始,然后继续,第52-53页,文档 va_list

    The va_list Type

    va_list类型是一个数组 包含一个的单个元素 包含必要的结构 实施va_arg的信息 宏. va_list的C定义 类型在图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];
    

    The va_start Macro

    va_start宏初始化 结构如下:

    reg_save_area 元素指向 寄存器保存区域的开始。

    overflow_arg_area 使用该指针 获取在传递的参数 堆栈.它用 传递的第一个参数的地址 堆栈(如果有),然后始终 更新以指向开始 堆栈上的下一个参数。

    gp_offset 元素包含偏移量 从reg_save_area到 下一个可用一般的地方 目的参数寄存器被保存.在 如果所有参数寄存器都是 耗尽,将其设置为值48 (6 * 8)。

    fp_offset 元素包含偏移量 从reg_save_area到 下一个可用浮动的地方 点参数寄存器被保存.在 如果所有参数寄存器都是 耗尽,将其设置为值304 (6 * 8 + 16 * 16)。

    p

    原来的问题是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 是数组类型,可能不是。

  • 2021-1-12
    2 #

    在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
    }
    

    就可以了! 而且您不必担心有多少论点。

  • java:哪些Swing组件方法是线程安全的?
  • iphone:如何在iOS的MKAnnotation中添加更多详细信息