首頁>Program>source

任何人都可以參考 va_list 在x86_64 ABI(Linux上使用的那个)中? 我正在尝試除錯一些堆棧或引數似乎已损壞的代碼,這確實有助於理解我應该所见...

最新回復
  • 1月前
    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 是陣列型別,可能不是。

  • 1月前
    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中添加更多详细資訊