在Win32 程序中每个进程都占有4GB的虚拟地址空间,这4G的地址空间内部又被分为代码段,全局变量段堆段和栈段,栈内存由函数使用,用来存储函数内部的局部变量,而堆是由程序员自己申请与释放的,系统在管理堆内存的时候采用的双向链表的方式,接下来将通过调试代码来分析堆内存的管理。

堆内存的双向链表管理

下面是一段测试代码

#include <iostream>
using namespace std; int main()
{
int *p = NULL;
__int64 *q = NULL;
int *m = NULL; p = new int;
if (NULL == p)
{
return -1;
}
*p = 0x11223344; q = new __int64;
if (NULL == q)
{
return -1;
}
*q = 0x1122334455667788; m = new int;
if (NULL == m)
{
return -1;
}
*m = 0x11223344; delete p;
delete q;
delete m;
return 0;
}

我们对这段代码进行调试,当代码执行到delete p;位置的时候(此时还没有执行delete语句)查看变量的值如下:

p q m变量的地址比较接近,这三个指针变量本身保存在函数的栈中。从图中看存储这三个变量内存的地址好像不像栈结构,这是由于在高版本的VS中默认开启了地址随机化,所以这里看不出来这些地址的关系,但是如果在VC6里面可以很明显的看到它们在一个栈结构中。

我们将p, q, m这三者所指向的内存都减去 0x20 得到

p - 0x20 = 0x00035cc8 - 0x20 = 0x00035ca8
q - 0x20 = 0x00035d08 - 0x20 = 0x00035ce8
m - 0x20 = 0x00035d50 - 0x20 = 0x00035d30

在内存窗口中分别查看p - 0x20, q- 0x20, m- 0x20 位置的内存如下

通过观察发现p - 0x20处前8个字节存储了两个地址分别是 0x00035c38、0x00035ce8。是不是对0x00035ce8 这个地址感到很熟悉呢,它就是q - 0x20 处的地址,按照这个思路我们观察这些内存发现

内存地址 前四个字节 后四个字节
0x00035ca8 0x00035c38 0x00035ce8
0x00035ce8 0x00035ca8 0x00035d30
0x00035d30 0x00035ce8 0x00000000

看到这些地址有没有发现什么呢?没错,这个结构有两个指针域,第一个指针域指向前一个节点,后一个指针域指向后一个节点,这是一个典型的双向链表结构,你没有发现?没关系,我们将这个地址整理一下得到下面这个图表

既然知道了它的管理方式,那么接着往后执行delete语句,这个时候再看这些地址对应的内存中保存的值

内存地址 前四个字节 后四个字节
0x00035CA8 0x00035d70 0x000300c4
0x00035ce8 0x00035c38 0x00035d30
0x00035d30 0x00035ce8 0x00000000

系统已经改变了后面两个节点中next和pre指针域的内容,将p节点从双向链表中除去了。而这个时候仔细观察p节点中存储内容发现里面得值已经变为 0xfeee 了。

我们在delete的时候并没有传入对应的参数告知系统该回收多大的内存,那么它是怎么知道该如何回收内存的呢。我们回到之前的那个p - 0x20 内存的图上看,是不是在里面发现了一个0x00000004的值,其实这个值就是当前节点占了多少个字节,如果不相信,可以看看q- 0x20 和m - 0x20 内存处保存的值看看,在对应的偏移处是不是有 8和4。系统根据这个值来回收对应的内存。


C 堆内存管理的更多相关文章

  1. Linux堆内存管理深入分析(下)

     Linux堆内存管理深入分析 (下半部) 作者@走位,阿里聚安全 0 前言回顾 在上一篇文章中(链接见文章底部),详细介绍了堆内存管理中涉及到的基本概念以及相互关系,同时也着重介绍了堆中chunk分 ...

  2. Linux堆内存管理深入分析(上)

    Linux堆内存管理深入分析(上半部) 作者:走位@阿里聚安全   0 前言 近年来,漏洞挖掘越来越火,各种漏洞挖掘.利用的分析文章层出不穷.从大方向来看,主要有基于栈溢出的漏洞利用和基于堆溢出的漏洞 ...

  3. Linux堆内存管理深入分析

    (上半部) 作者:走位@阿里聚安全 前言 近年来,漏洞挖掘越来越火,各种漏洞挖掘.利用的分析文章层出不穷.从大方向来看,主要有基于栈溢出的漏洞利用和基于堆溢出的漏洞利用两种.国内关于栈溢出的资料相对较 ...

  4. C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...

  5. Linux堆内存管理深入分析 (上半部)【转】

    转自:http://www.cnblogs.com/alisecurity/p/5486458.html Linux堆内存管理深入分析(上半部) 作者:走位@阿里聚安全 0 前言 近年来,漏洞挖掘越来 ...

  6. Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解

    C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...

  7. 栈 & 堆 |--> 内存管理

    内存管理: 栈区 [stack]:由编译器自动分配并释放,一般存放函数的参数值,局部变量等 堆区 [heap]:由程序员分配和释放,如果程序员不释放,程序结束时,可能会由操作系统回收 全局区(静态区) ...

  8. Dalvik 堆内存管理与回收

    Dalvik虚拟机用来分配对象的堆划分为两部分,一部分叫做Active Heap,另一部分叫做Zygote Heap.下面基于管理机制来介绍为何分配为这两部分,以及堆内存的管理. 我们从Android ...

  9. JVM堆内存管理与自定义分配参数详解

    堆内存模型: 在Java中,堆被划分成两个不同的区域:新生代(Young),老年代(Old).而Permanent属于永久代(方法区),不属于堆内存.新生代又被分为了三个区域:Eden,from  s ...

随机推荐

  1. redis 3.0 集群__安装

    参考文档 http://redis.io/topics/cluster-tutorial http://redis.io/topics/cluster-spec http://redis.readth ...

  2. centos6安装mysql5.7

    RPM包安装与卸载mysql 建议:装完mysql后立刻创建一个密码,不然下次登录的时候会有问题.原因是mysql 5.7会自动创建一个临时密码,过期失效,可以到grep "password ...

  3. POJ3074 Sudoku

    POJ3074 Sudoku 与POJ2676相比,这一题搜索时每一步都找到最好确定的点进行枚举 对于每行.每列.每个九宫格,都分别用一个9位二进制数保存还有那些数还可以填 对于每个位置,将其所在行. ...

  4. 题目1021:统计字符(hash简单应用)

    问题来源 http://ac.jobdu.com/problem.php?pid=1021 问题描述 每次输入两个字符串,统计第一个字符串中的每个字符在第二个字符串中出现的次数. 问题分析 太明显了, ...

  5. 海思3519A上移植OpenCV3.x

    环境安装与准备 下载opencv3.4.1. 或者 下载opencv3.2.0. 进入到opencv所在的目录新建目录build,install 安装cmake: apt-get install cm ...

  6. NavigatorIOS

    使用 NavigatorIOS,我们需要给他指定一个路由,这样它才能知道显示哪个页面 实例化 Navigator 需要2个必要的属性 —— initialRoute 和 renderSence,它们的 ...

  7. 20190430-Bootstrapの组件

    写在前面的乱七八糟:今天务必要把BT盘完~任重道远~ 目录 1.字体图标 2.下拉菜单 3.按钮组 4.输入框组 5.导航 5.1标签页 5.2胶囊式标签页 5.3路径导航/面包屑导航 6.导航条 7 ...

  8. Centos 7搭建Gitlab服务器(一),搭配文章(二)一起使用,效果更好

    一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开系统防火墙中的HTTP和SSH端口访问. 1.安装ss ...

  9. erlang随笔3--OTP

    OTP最核心的概念就是行为.一个行为封装了某种常见的行为模式.可以把这些行为理解为某种应用程序框架.可以通过回调模块来 定制这些框架.OTP依靠行为引用了容错,扩容和动态代码升级等特性.所以在写回调模 ...

  10. oracle--dump块信息操作

    01, 查看表 SQL> select * from tab where TNAME='T'; TNAME TABTYPE ----------------------------------- ...