[英]what happens when tried to free memory allocated by heap manager, which allocates more than asked for?
[英]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 上以其他方式在寄存器中傳遞的函數參數。 因此編譯器需要分配額外的堆棧空間,以便argc
和argv
參數可以“溢出”。 您可以在程序集的第 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。
如果編譯器更加小心並且沒有浪費argc
和argv
之間的 4 個字節,我們本可以只剩下 512 個字節。 但是,使用 528 的一個好處是緩沖區str
最終以 16 字節對齊。 這對於最小對齊僅為 1 的char
數組不是必需的,但它可以使strcpy
等字符串函數更有效地使用快速 SIMD 算法。 我不確定編譯器是故意這樣做還是只是巧合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.