我想在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)
所以我能理解前三行,我需要一些帮助才能理解其余部分
感谢您的关注!
标准免责声明:一个实现可能完全不同,但大多数在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_used
和allocated
计数器的存储)将在堆栈上分配.
假设一个典型的32位机器,其中指针和size_ts各为32位,这意味着堆栈上有12个字节的空间.对于更简单的类型(例如,int
或者long
),甚至可以想象类似的东西vector
,我们期望在很多情况下看到寄存器在寄存器中分配.编译器基于(猜测)可能最常使用的选择在寄存器中分配哪个.在像SPARC或具有大量寄存器的Itanium这样的机器上,我们可以预期大多数本地/自动变量都在寄存器中.在x86上,我们有足够少的寄存器,堆栈使用非常普遍(尽管x86-64是可用寄存器的两倍,这有很大帮助).
然后,向量本身使用该Allocator
对象来存储其他位置(通常,但不一定是免费存储)以存储您关心的数据(即,您存储在向量中的元素).
查看您包含的代码的具体细节:在我看来,大多数其余代码都在调用std::string
对象的构造函数和析构函数.不幸的是,你使用了可怕的AT&T语法,这使得它几乎无法读取.
自动变量通常在堆栈上分配,但是它们的实现当然可以使用其他内存.对于标准容器,它们将使用动态内存分配或任何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)