簡體   English   中英

為什么我的緩沖區在堆棧上分配的內存比我要求的多?

[英]Why my buffer got more memory allocated on stack than what I asked for?

這是我的源代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 500

int main(int argc, char** argv)
{
        if (argc != 2)
                exit(1);
        char str[MAX];
        strcpy(str, argv[1]);
        return 0;
}

我使用gdb disas sembled main並得到以下結果:

Dump of assembler code for function main:
   0x0000000000001145 <+0>:     push   %rbp
   0x0000000000001146 <+1>:     mov    %rsp,%rbp
   0x0000000000001149 <+4>:     sub    $0x210,%rsp
   .
   .
   .
End of assembler dump.

這里值得注意的是:

0x0000000000001149 <+4>: sub $0x210,%rsp

我的問題是——
為什么應該是$0x1f4 (500 字節) $0x1f4$0x210 (528 字節),因為這是我要求的?

我猜你正在使用 gcc 並在沒有優化的情況下進行編譯,就像這樣 (godbolt)

這里發生了幾件事:

首先,在沒有優化的情況下編譯時,編譯器會嘗試確保每個局部變量在內存中都有一個地址,以便調試器可以輕松檢查或修改它。 這包括在 x86-64 上以其他方式在寄存器中傳遞的函數參數。 因此編譯器需要分配額外的堆棧空間,以便argcargv參數可以“溢出”。 您可以在程序集的第 5 行和第 6 行看到溢出:

        movl    %edi, -516(%rbp)
        movq    %rsi, -528(%rbp)

如果仔細觀察,您可能會注意到,當-520(%rbp)可用時,編譯器將argc (來自%edi )放置在地址-516(%rbp)處浪費了 4 個字節。 不完全清楚為什么,但畢竟,它不是優化! 這樣我們就得到了 516 個字節。

另一個問題是 x86-64 ABI 需要 16 字節堆棧對齊; 請參閱為什么 x86-64 / AMD64 System V ABI 要求 16 字節堆棧對齊? . 在這種情況下,長話短說,這意味着我們的堆棧調整需要是 16 字節的倍數。 (返回地址和推入的rbp添加 16 個字節,這不會干擾這種對齊。)所以我們的 516 必須四舍五入到 16 的下一個倍數,即 528。

如果編譯器更加小心並且沒有浪費argcargv之間的 4 個字節,我們本可以只剩下 512 個字節。 但是,使用 528 的一個好處是緩沖區str最終以 16 字節對齊。 這對於最小對齊僅為 1 的char數組不是必需的,但它可以使strcpy等字符串函數更有效地使用快速 SIMD 算法。 我不確定編譯器是故意這樣做還是只是巧合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM