美文网首页
栈里面的红色区域

栈里面的红色区域

作者: stockholder | 来源:发表于2017-07-28 02:37 被阅读0次

红色区域概念

当一个函数里面没有调用其他函数时,在函数的内部会有一块区域用来存储局部变量和参数,这块区域就叫红色区域(默认区域大小是128字节)

下面的例子是用来说明编译器是如何处理函数内部有其他函数调用和没有其他函数调用的的。
  • 函数内部不调用其他函数时的情况
int test1(int a,int b) {
    int c = 3;
    int d = 4;
    int e = a + b +c +d;
    return e;
}

int main(int argc, char * argv[]) {
        int m = test1(1, 2);
        NSLog(@"%d",m);
}

上面是一个简单的函数定义,看一下test1()内部的反汇编代码

RedDistinct`test1:
    0x100f2c990 <+0>:  pushq  %rbp
    0x100f2c991 <+1>:  movq   %rsp, %rbp
    0x100f2c994 <+4>:  movl   %edi, -0x4(%rbp)
    0x100f2c997 <+7>:  movl   %esi, -0x8(%rbp)
->  0x100f2c99a <+10>: movl   $0x3, -0xc(%rbp)
    0x100f2c9a1 <+17>: movl   $0x4, -0x10(%rbp)
    0x100f2c9a8 <+24>: movl   -0x4(%rbp), %esi
    0x100f2c9ab <+27>: addl   -0x8(%rbp), %esi
    0x100f2c9ae <+30>: addl   -0xc(%rbp), %esi
    0x100f2c9b1 <+33>: addl   -0x10(%rbp), %esi
    0x100f2c9b4 <+36>: movl   %esi, -0x14(%rbp)
    0x100f2c9b7 <+39>: movl   -0x14(%rbp), %eax
    0x100f2c9ba <+42>: popq   %rbp
    0x100f2c9bb <+43>: retq 

通过汇编代码分析,此时sp寄存器没有开辟栈空间来放这些参数和局部变量,是通过是通过bp指针减来存放参数和局部变量(直接从寄存器取值放到栈里面),那么如果这样的话,当调用其他函数时,不是会push到栈里面,将参数或者是局部变量覆盖了?那么实际的情况又是怎样的呢?

屏幕快照 2017-07-28 上午1.59.49.png
  • 函数内部调用其他函数时的情况
void test2() {  
}
int test1(int a,int b) {
    int c = 3;
    int d = 4;
    int e = a + b +c +d;
    test2();
    return e;
}
int main(int argc, char * argv[]) {
        int m = test1(1, 2);
        NSLog(@"%d",m);
}

下面是反汇编代码

RedDistinct`test1:
    0x10556a980 <+0>:  pushq  %rbp
    0x10556a981 <+1>:  movq   %rsp, %rbp
    0x10556a984 <+4>:  subq   $0x20, %rsp
    0x10556a988 <+8>:  movl   %edi, -0x4(%rbp)
    0x10556a98b <+11>: movl   %esi, -0x8(%rbp)
->  0x10556a98e <+14>: movl   $0x3, -0xc(%rbp)
    0x10556a995 <+21>: movl   $0x4, -0x10(%rbp)
    0x10556a99c <+28>: movl   -0x4(%rbp), %esi
    0x10556a99f <+31>: addl   -0x8(%rbp), %esi
    0x10556a9a2 <+34>: addl   -0xc(%rbp), %esi
    0x10556a9a5 <+37>: addl   -0x10(%rbp), %esi
    0x10556a9a8 <+40>: movl   %esi, -0x14(%rbp)
    0x10556a9ab <+43>: callq  0x10556a970               ; test2 at main.m:12
    0x10556a9b0 <+48>: movl   -0x14(%rbp), %eax
    0x10556a9b3 <+51>: addq   $0x20, %rsp
    0x10556a9b7 <+55>: popq   %rbp
    0x10556a9b8 <+56>: retq 

可以看到当函数内部有其他函数的调用时,会开辟一块栈空间(通过下面的汇编代码可以看出,开辟了32个字节的栈空间,并且该栈空间会随着参数或者局部变量的数目来增加,这样的方式不用去操作栈,速度快)
0x10556a984 <+4>: subq $0x20, %rsp
用来存放这些参数和局部变量,这个时候就不会出现调用其他函数会将局部变量和参数覆盖掉了,编译器还是很聪明的。

屏幕快照 2017-07-28 上午2.33.02.png
小结一下:

当一个函数里面没有调用其他函数时,在函数的内部会有一块区域用来存储局部变量和参数(不会开辟栈空间来存储,但是当128字节不够用的话还是会开辟栈空间),这块区域就叫红色区域,当有调用其他函数时,会开辟栈空间(这块区间也叫做栈帧)来存储局部变量和参数,用来保护参数和局部变量不被覆盖。

相关文章

  • 栈里面的红色区域

    红色区域概念 当一个函数里面没有调用其他函数时,在函数的内部会有一块区域用来存储局部变量和参数,这块区域就叫红色区...

  • Java中的堆与栈

    栈可以理解为内存中一片连续的区域,而堆可以理解为内存中一片分散的区域。可以说,栈是用来运行程序的区域,当在栈里应用...

  • 红色区域

  • JVM内存模型

    JVM内存区域 JVM内存区域主要分为线程私有区域【程序计数器,虚拟机栈,本地方法栈】,线程共享区域【JAVA堆,...

  • 内存

    内存的几大区域 栈内存和堆内存 所谓的栈内存和堆内存并不是内存里面有一块区域叫栈,有一块区域叫堆.所谓的栈内存和对...

  • 十九. 红色区域

    为甚test调用sum的时候,要去往上走好多位置?必须往上走,因为有可能test的空间被push过来的sum参数覆...

  • JVM内存区域

    JVM规范的内存区域: JVM Specification中规定的内存区域包括:程序计数器、Java栈、本地方法栈...

  • 内存管理

    内存管理的原理? 内存空间总共有8块区域,有两个区域需要特别注意,一个就是堆空间,一个就是栈空间。栈里存放临时变量...

  • 随谈Java - (二)内存区域

    一、JVM内存区域规范 1.1 各区域作用 Java方法栈:以栈的形式存放栈帧,每一个Java方法调用的开始和结束...

  • [PLT] 类型图示

    红色区域外:well behaved (type soundness)红色区域内:ill behaved 如果所有...

网友评论

      本文标题:栈里面的红色区域

      本文链接:https://www.haomeiwen.com/subject/vcxxlxtx.html