数组在堆栈上的内存分配 [英] Arrays memory allocation on stack

查看:229
本文介绍了数组在堆栈上的内存分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C语言中有2个功能:

I have 2 functions in C:

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

gcc 7.3 x86-64

-O0 -g

操作系统:

16.04.1-Ubuntu x86-64

16.04.1-Ubuntu x86-64

产生的intel汇编功能:

Produced intel assembly of functions:

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字节.

I can see that for 50 bytes array 64 bytes were allocated. It seems that it's allocating stack on 16 bytes boundary, since for 10 bytes - 16 bytes were allocated.

我的问题:

1)在数组的16个字节边界上是否有一些堆栈对齐标准? 导致诸如int,long int等变量明显不在16字节边界上分配.

1) Is there some standard of stack alignment on 16 byte boundary for arrays? Cause variables like int, long int, etc. clearly aren't allocated on 16 byte boundary.

2)为什么以这种奇怪的方式分配数组?我们可以看到a 14个字节数组,它们是在 50个字节的有效载荷之后 c1>, 6个对齐字节被分配在 10个字节的有效载荷之前.我想念什么吗?

2) Why arrays allocated in such a weird way? We can see for array a, 14 bytes that were added as alignment padding right after our payload of 50 bytes, but for array b, 6 alignment bytes are allocated before our payload of 10 bytes. Am i missing something?

3)为什么将函数参数传入EDI(unsigned char x),并放在距数组内存开头4个字节的堆栈上(包括填充).那么字节变量(AL register)也被填充了吗?为什么 4个字节?

3) Why function argument passed in EDI (unsigned char x), placed on stack 4 bytes away from our arrays memory beginning(including padding). So byte variables(AL register) are also padded or something? Why 4 bytes?

推荐答案

x86_64 abi需要16字节的堆栈对齐方式(输入函数时,堆栈指针必须为16字节对齐方式).但是您看到的过度对齐是由-O0引起的;如果-O1或更高,则阵列的排列效率更高.例如

x86_64 abi requires a 16 byte stack alignment (stack pointer must be 16 byte aligned when entering a function). But the overalignment seen by you is caused by -O0; with -O1 or higher, the arrays are aligned more efficiently. E.g.

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创建其他布局.

这篇关于数组在堆栈上的内存分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆