C++内存管理

一个由C/C++编译的程序占用的内存分为以下几个部分

  1. 栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  2. 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
  3. 全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
  4. 文字常量区:常量字符串就是放在这里的。 程序结束后由系统释放
  5. 程序代码区:存放函数体的二进制代码。

main.cpp
虚拟内存区域分配如图所示:
内存分配方向

一个简化的进程地址空间模型:https://www.zhihu.com/question/36103513/answer/66101372
简化进程地址空间模型

// 简单测试
void main(){
    int i=0;
   char c[4];
   int j=0;
   strcpy(c,"54321")
   // 求 i,j 的值?
}

由于i,c,j都分配在栈空间,从高地址向低地址增长,因此5个字节的字符串放入4字节的数组空间,溢出一个字节,字符'1'的ascii码46,会覆盖高地址空间的变量i的高位,由于c++内存布局使用小端编码方式(0x12345678编码为[78 56 34 12]),因此i的内存被覆盖为[2E 00 00 00](2E=46),即i的值变为数字46

进程内存地址空间被划分为8块(Managed Heap是另一种内存堆),并且各块内存不是聚集在一起形成连续内存块,而是按需加载使用内存;他们的详细情况如下:

由于编译器在后台做了大量的内存管理自动化工作,因此程序设计过程中主要关注的内存区域类型有:Stack、Heap、Free(Free Virtual Address Space),下面我们对这几种做一个简要介绍:

Stack 是一块固定大小的连续内存,受运行时管理,无需用户自行分配和回收;当函数调用嵌套层次非常深时会产生 Stack overflow(堆栈溢出)错误,如递归调用、循环调用、消息循环、大对象参数、大对象局部变量等都容易触发堆栈溢出;

Heap 主要用于管理小内存块,是一个内存管理单元,默认为1MB,可动态增长;每一个应用程序默认有一个 Heap,用户也可以创建自己的 Heap,new/delete, malloc/free 都是从堆中直接分配内存块;

Free(Free Virtual Address Space)即进程空间中的整个可用地址空间,它会以两种方式被使用,一种是Heap 自动分配和回收,一种是直接使用VirtualAlloc/VirtualFree 分配和回收;用户对它的直接使用是用于分配连续大块内存,分配和释放的速度比使用 Heap 更快;

几个值得注意的问题

  1. 虚函数表是class specific的,也就是针对一个类来说的,这里有点像一个类里面的staic成员变量,即它是属于一个类所有对象的,不是属于某一个对象特有的,是一个类所有对象共有的。
  2. 虚函数表是编译器来选择实现的,编译器的种类不同,可能实现方式不一样,就像前面我们说的vptr在一个对象的最前面,但是也有其他实现方式,不过目前gcc 和微软的编译器都是将vptr放在对象内存布局的最前面。
  3. 虽然我们知道vptr指向虚函数表,那么虚函数表具体存放在内存哪个位置呢,虽然这里我们已经可以得到虚函数表的地址。实际上虚函数指针是在构造函数执行时初始化的,而虚函数表是存放在可执行文件中的。下面的一篇博客测试了微软的编译器将虚函数表存放在了目标文件或者可执行文件的常量段中,http://blog.csdn.net/vicness/article/details/3962767
  4. 经过测试,在gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段.rodata中。
  5. 虚函数表vtable在Linux/Unix中存放在可执行文件的只读数据段中(rodata),这与微软的编译器将虚函数表存放在常量段存在一些差别。

Linux进程在虚拟内存中的标准内存段布局

参考:
https://blog.csdn.net/yangle4695/article/details/52153143

https://www.cnblogs.com/zhoug2020/p/6025388.html

虚函数表存放在哪里

Linux虚拟地址空间布局以及进程栈和线程栈总结


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 using1174@foxmail.com

文章标题: C++内存管理

文章字数: 1,236

本文作者: Jun

发布时间: 2018-04-20, 18:49:00

最后更新: 2022-03-09, 14:28:39

原始链接: http://yoursite.com/2018/04/20/C-内存管理/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏