gpt4 book ai didi

c - 堆栈上的数组内存分配

转载 作者:太空宇宙 更新时间:2023-11-04 01:18:46 24 4
gpt4 key购买 nike

我在 C 中有 2 个函数:

void func1(unsigned char x)
{
unsigned char a[10][5];

a[0][0] = 1;
a[9][4] = 2;
}

void func2(unsigned char x)
{
unsigned char a[10][5];

a[0][0] = 1;
a[9][4] = 2;

unsigned char b[10];

b[0] = 4;
b[9] = 5;
}

编译:

gcc 7.3 x86-64

-O0 -g

操作系统:

16.04.1-Ubuntu x86-64

生成的函数的英特尔汇编:

func1(unsigned char):
pushq %rbp
movq %rsp, %rbp
movl %edi, %eax
movb %al, -68(%rbp)
movb $1, -64(%rbp)
movb $2, -15(%rbp)
nop
popq %rbp
ret

func2(unsigned char):
pushq %rbp
movq %rsp, %rbp
movl %edi, %eax
movb %al, -84(%rbp)
movb $1, -64(%rbp)
movb $2, -15(%rbp)
movb $4, -74(%rbp)
movb $5, -65(%rbp)
nop
popq %rbp
ret

我可以看到,对于 50 个字节的数组,分配了 64 个字节。它似乎在 16 字节边界上分配堆栈,因为对于 10 字节 - 分配了 16 字节。

我的问题:

1) 数组的 16 字节边界是否有一些堆栈对齐标准?导致像 int、long int 等变量显然没有分配在 16 字节边界上。

2) 为什么数组以如此奇怪的方式分配?我们可以看到对于数组 a14 字节 添加为对齐填充 紧接 我们的 50 字节 负载,但对于数组 b6 个对齐字节 分配在 之前 我们的 10 字节 负载。我错过了什么吗?

3) 为什么函数参数在 EDI 中传递(unsigned char x),放置在距数组内存开始(包括填充)4 个字节的堆栈中。所以字节变量(AL register)也被填充了还是什么?为什么是 4 字节

最佳答案

x86_64 abi 要求 16 字节堆栈对齐(进入函数时堆栈指针必须 16 字节对齐)。但是你看到的过度对齐是由-O0引起的;使用 -O1 或更高版本,数组对齐更有效。例如

void func2(unsigned char x)
{
unsigned char a[10][5];

a[0][0] = 1;
a[9][4] = 2;

unsigned char b[10];

b[0] = 4;
b[9] = 5;

__asm__ __volatile__("" :: "r"(a), "r"(b) : "memory");
}

原因:

gcc -O1 -g x.c -c
objdump -d x.o
0000000000000010 <func2>:
10: c6 44 24 c0 01 movb $0x1,-0x40(%rsp)
15: c6 44 24 f1 02 movb $0x2,-0xf(%rsp)
1a: c6 44 24 b6 04 movb $0x4,-0x4a(%rsp)
1f: c6 44 24 bf 05 movb $0x5,-0x41(%rsp)
24: 48 8d 44 24 c0 lea -0x40(%rsp),%rax
29: 48 8d 54 24 b6 lea -0x4a(%rsp),%rdx
2e: c3 retq

-Os-O3 创建其他布局。

关于c - 堆栈上的数组内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49707610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com