c++ - 自动对象住在哪里(附演示)

标签 c++ assembly

我想对c++ 的内存管理及其实现(如g++、vc++)做一些研究。

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

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

#include <string>

void autovar(){
    std::string 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//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

所以我能理解前 3 行,我需要一些帮助才能理解其余的

感谢您的关注!

最佳答案

标准免责声明:一个实现可以完全不同地工作,但大多数在 x86 或类似平台上,可能大致如下所述。

当您定义一个具有自动存储持续时间的对象时,该对象自身 将被分配到堆栈上。因此,让我们考虑一个稍微简化的 vector 版本:

template <class T, class Allocator = std::allocator<T> >
class vector {
    T *data;
    size_t currently_used;
    size_t allocated;
public:
    // ...
};

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

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

vector 本身然后使用 Allocator 对象在别处获取存储空间(通常,但不一定是免费存储空间)来存储您关心的数据(即您存储的元素 vector )。

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

关于c++ - 自动对象住在哪里(附演示),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16542749/

相关文章:

c++ - 列表初始化(使用花括号)有什么好处?

assembly - 为什么 avr-gcc 将 "push r1"指令添加到函数的开头?

multithreading - SFENCE 是否会阻止存储缓冲区对 MESI 隐藏更改?

c++ - 将 for 循环转换为使用 std::transform

c++ - 用于本地网络的在线 c/c++ 编译器

c++ - 枚举完全设置为 0

c - 在不使用占位符的情况下在 C 中使用汇编器

windows - Win32 ASM 程序不向命令行打印任何内容

linux - objdump -S 不显示 Linux 内核模块的源代码列表

c++ - 无法从 int 推断出 'const' ... 的模板参数