自动对象在哪里(使用演示)

zou*_*yjs 1 c++ assembly

我想在c ++的内存管理方面做一些研究,它的实现就像g ++,vc ++.

第一个问题是自动对象(本地对象)在哪里?(内置类型,用户定义类型,STL ......)

我认为内置类型存储在堆栈中,这在编译步骤中完成.对于用户定义的类型,事实是什么?我之前看到的地方是STL数据类型总是在堆内存中.所以我写了一个很小的函数,用g ++编译,用objdump反汇编,看看编译器真正做了什么.

#include <string>

void autovar(){
    std::string s;
}
Run Code Online (Sandbox Code Playgroud)

拆解的结果如下:

00000000 <__Z7autovarv>:
   0:   55                      push   %ebp //push the old frame pointer 
   1:   89 e5                   mov    %esp,%ebp //ebp point to the old
   3:   83 ec 28                sub    $0x28,%esp//allocate stack space
   6:   8d 45 f4                lea    -0xc(%ebp),%eax//param or something??
   9:   89 04 24                mov    %eax,(%esp)
   c:   e8 00 00 00 00          call   11 <__Z7autovarv+0x11>
  11:   8d 45 f4                lea    -0xc(%ebp),%eax
  14:   89 04 24                mov    %eax,(%esp)
  17:   e8 00 00 00 00          call   1c <__Z7autovarv+0x1c>
  1c:   c9                      leave
  1d:   c3                      ret
  1e:   90                      nop
  1f:   90                      nop
Run Code Online (Sandbox Code Playgroud)

所以我能理解前三行,我需要一些帮助才能理解其余部分

感谢您的关注!

Jer*_*fin 9

标准免责声明:一个实现可能完全不同,但大多数在x86或类似的,可能会大致如下所述.

当您定义具有自动存储持续时间的对象时,该对象本身将在堆栈上分配.那么,让我们考虑一个矢量的简化版本:

template <class T, class Allocator = std::allocator<T> >
class vector {
    T *data;
    size_t currently_used;
    size_t allocated;
public:
    // ...
};
Run Code Online (Sandbox Code Playgroud)

因此,当我们分配a时vector,该对象本身(data指针currently_usedallocated计数器的存储)将在堆栈上分配.

假设一个典型的32位机器,其中指针和size_ts各为32位,这意味着堆栈上有12个字节的空间.对于更简单的类型(例如,int或者long),甚至可以想象类似的东西vector,我们期望在很多情况下看到寄存器在寄存器中分配.编译器基于(猜测)可能最常使用的选择在寄存器中分配哪个.在像SPARC或具有大量寄存器的Itanium这样的机器上,我们可以预期大多数本地/自动变量都在寄存器中.在x86上,我们有足够少的寄存器,堆栈使用非常普遍(尽管x86-64是可用寄存器的两倍,这有很大帮助).

然后,向量本身使用该Allocator对象来存储其他位置(通常,但不一定是免费存储)以存储您关心的数据(即,您存储向量中的元素).

查看您包含的代码的具体细节:在我看来,大多数其余代码都在调用std::string对象的构造函数和析构函数.不幸的是,你使用了可怕的AT&T语法,这使得它几乎无法读取.


zch*_*zch 6

自动变量通常在堆栈上分配,但是它们的实现当然可以使用其他内存.对于标准容器,它们将使用动态内存分配或任何Allocator用户供应.因此,在示例中,s对象位于堆栈上,但它的数据可能位于其他位置(如果它不是空的).

你的装配评论:

00000000 <__Z7autovarv>:
   0:   55                      push   %ebp //push the old frame pointer 
   1:   89 e5                   mov    %esp,%ebp //ebp point to the old
   3:   83 ec 28                sub    $0x28,%esp //allocate stack space
   6:   8d 45 f4                lea    -0xc(%ebp),%eax
        //store address of `s` (which is 12 bytes below %ebp) in eax
   9:   89 04 24                mov    %eax,(%esp) //put it on a stack (argument)
   c:   e8 00 00 00 00          call   11 <__Z7autovarv+0x11> //call constructor
  11:   8d 45 f4                lea    -0xc(%ebp),%eax
  14:   89 04 24                mov    %eax,(%esp)
  17:   e8 00 00 00 00          call   1c <__Z7autovarv+0x1c> //call destructor
  1c:   c9                      leave //restore esp and ebp
  1d:   c3                      ret //return
  1e:   90                      nop
  1f:   90                      nop
Run Code Online (Sandbox Code Playgroud)