文档章节

内存管理[3]

涂孟超
 涂孟超
发布于 2014/09/26 15:36
字数 1238
阅读 6
收藏 0
点赞 0
评论 0
VirtualAlloc 分配的内存是以 4K 为最小单位、连续的内存地址(但映射到真实的内存时它不一定是连续的), 前面说了, 它不适合分配小内存(譬如只有几个字节的变量); 局部的变量在 "栈" 中有程序自动管理, 那么那些全局的小变量怎么办呢? 这就要用到 "堆".

这样看来, VirtualAlloc 分配的内存既不是 "栈" 也不是 "堆"; VirtualAlloc 分配的内存地址是连续的, "堆" 中内容一般是不连续的, 所以管理 "堆" 比较麻烦, 它是通过双线链表的结构方式管理的; 程序可以拥有若干个 "堆", 每一个 "堆" 都会有一个句柄, 访问 "堆" 中的内容时先要找到这个 "堆", 然后再遍历链表, 这可能就是 "堆" 比 "栈" 慢的根本原因.

在 "堆" 中分配内存(HeapAlloc)前先要建立 "堆"(HeapCreate), 就像程序有默认的 "栈" 一样, 每一个程序都有一个默认建立的 "堆"(可以用 GetProcessHeap 获取这个 "默认堆" 的句柄), 我们在 Delphi 中用到 "堆" 时, 使用的就是这个 "默认堆". 如果让程序更灵活地拥有多个 "堆", 必须要用到 API 函数.

建立 "堆" 时会同时提交真实内存的, 这在申请大内存时会很慢, 所以默认堆也只有 1M, 但 "默认堆" 并没有限制大小, 它会根据需要动态增长.

有了 "默认堆" 还有必要申请其他的 "堆" 吗? 这只有在多线程中才能体现出来, 和 "栈" 不一样, 程序会给每个线程分配一个 "栈区"; 而 "默认堆" 是进程中的所有线程公用的, 当一个线程使用 "默认堆" 时, 另一个需要使用 "堆" 的线程就要先挂起等待, 也就是它们不能同时使用; 只有通过 API 函数重新建立的私有堆才是互不干涉、最有效率的.

先了解一下 "堆" 相关的函数.
//建立堆; 注意建立时指定的尺寸也是按页大小(PageSize)对齐的, 譬如指定 15k, 实际会分配 16K.
HeapCreate(
  flOptions: DWORD;     {堆属性选项, 见下表}
  dwInitialSize: DWORD; {初始尺寸, 单位是字节; 该大小会被直接提交到实际的内存}
  dwMaximumSize: DWORD  {最大尺寸, 如果不限定最大值就设为 0}
): THandle;             {返回堆句柄; 失败返回 0, 但如果参数 flOptions 允许了异常, 失败会返回异常标识}

//flOptions 参数可选值:
HEAP_NO_SERIALIZE        = 1; {非互斥, 此标记可允许多个线程同时访问此堆}
HEAP_GENERATE_EXCEPTIONS = 4; {当建立堆出错时, 此标记可激发一个异常并返回异常标识}
HEAP_ZERO_MEMORY         = 8; {把分配的内存初始化为 0}

//flOptions 参数指定有 HEAP_GENERATE_EXCEPTIONS 时, 可能返回的异常:
STATUS_ACCESS_VIOLATION = DWORD($C0000005); {参数错误}
STATUS_NO_MEMORY        = DWORD($C0000017); {内存不足}

 
 
 
 
 

 

 

  
//销毁堆 HeapDestroy( hHeap: THandle {堆句柄} ): BOOL; {}
//从堆中申请内存 HeapAlloc( hHeap: THandle; {堆句柄} dwFlags: DWORD; {内存属性选项, 见下表} dwBytes: DWORD {申请内存的大小, 单位是字节} ): Pointer; {返回内存指针; 失败返回 0 或异常, 情况和建立堆是一样} //dwFlags 参数可选值: HEAP_NO_SERIALIZE = 1; {非互斥, 此标记可允许多个线程同时访问此堆} HEAP_GENERATE_EXCEPTIONS = 4; {当建立堆出错时, 此标记可激发一个异常并返回异常标识} HEAP_ZERO_MEMORY = 8; {把分配的内存初始化为 0} {能看出这和堆的属性选项是一样的; 如果 dwFlags 参数设为 0, 将使用堆的属性; 如果重新指定将覆盖堆的属性} {另外: 如果堆是默认堆, 也就是堆句柄来自 GetProcessHeap, dwFlags 参数会被忽略}
//改变堆内存的大小, 也就是重新分配 HeapReAlloc( hHeap: THandle; {句柄} dwFlags: DWORD; {内存属性选项; 该参数比 HeapAlloc 多出一个选项, 见下表} lpMem: Pointer; {原内存指针} dwBytes: DWORD {新的尺寸} ): Pointer; {同 HeapAlloc} //dwFlags 参数可选值: HEAP_NO_SERIALIZE = 1; {非互斥, 此标记可允许多个线程同时访问此堆} HEAP_GENERATE_EXCEPTIONS = 4; {当建立堆出错时, 此标记可激发一个异常并返回异常标识} HEAP_ZERO_MEMORY = 8; {把分配的内存初始化为 0} HEAP_REALLOC_IN_PLACE_ONLY = 16; {此标记不允许改变原来的内存位置}
//获取堆中某块内存的大小 HeapSize( hHeap: THandle; {堆句柄} dwFlags: DWORD; {内存属性; 可选值是 0 或 HEAP_NO_SERIALIZE, 后者可确保同步访问} lpMem: Pointer {内存指针} ): DWORD; {成功返回字节为单位的大小; 失败返回 $FFFFFFFF}
//释放堆中指定的内存块 HeapFree( hHeap: THandle; {堆句柄} dwFlags: DWORD; {内存属性; 可选值是 0 或 HEAP_NO_SERIALIZE} lpMem: Pointer {内存指针} ): BOOL; {}
//验证堆 HeapValidate( hHeap: THandle; {} dwFlags: DWORD; {} lpMem: Pointer {} ): BOOL; {}
//整理堆 HeapCompact( hHeap: THandle; {} dwFlags: DWORD {} ): UINT; {}
//锁定堆 HeapLock( hHeap: THandle {} ): BOOL; {}
//锁定后的解锁 HeapUnlock( hHeap: THandle {} ): BOOL; {}
//列举堆中的内存块 HeapWalk( hHeap: THandle; {} var lpEntry: TProcessHeapEntry {} ): BOOL; {}
举例放下篇吧.

本文转载自:http://www.cnblogs.com/del/archive/2008/05/08/1188715.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2004
码字总数 14107
作品 0
深圳
程序员
操作系统——存储管理

操作系统——存储管理 该部分功能: 1、地址映射(逻辑地址——>主存物理地址) 由操作系统中的装入程序loader来完成(静态或动态<执行时重定位寄存器完成>)。 2、内存分配和回收 3、存储保...

艾柯 ⋅ 2014/03/14 ⋅ 0

Memcached与Redis(三)

3. Memcached和Redis关键技术对比 作为内存数据缓冲系统,Memcached和Redis均具有很高的性能,但是两者在关键实现技术上具有很大差异,这种差异决定了两者具有不同的特点和不同的适用条件。下...

liujing07 ⋅ 2017/11/12 ⋅ 0

OC内存管理常见的面试题

#####面试:说一说对内存管理的理解?(原理) - 手动内存管理(MRC):1.在创建一个对象的时候系统会自动创建这个对象的引用计数并赋值为1;2.当引用计数为0的时候,对象会去调用dealloc方法来...

鹿微微鹿 ⋅ 2016/03/25 ⋅ 0

tcmalloc jemalloc glibc内存分配管理模块性能测试对比

tcmalloc是谷歌提供的内存分配管理模块 jemalloc是FreeBSD提供的内存分配管理模块 glibc是Linux提供的内存分配管理模块 并发16个线程,分配压测3次,每次压15分钟,可以看到谷歌的tcmalloc内...

技术小甜 ⋅ 2017/11/08 ⋅ 0

iOS中的内存管理(上)

下列行为都会增加一个app的内存占用: 1、创建一个OC对象; 2、定义一个变量; 3、调用一个函数或者方法。 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验。如何让...

傲风凌寒 ⋅ 2014/05/20 ⋅ 0

深入理解Linux内存管理-之-目录导航

转自:https://blog.csdn.net/gatieme/article/details/52384965 1 内存描述 2 页表管理 3 初始化内存管理

zwfgogo ⋅ 04/20 ⋅ 0

内存管理学习整理

内存管理梳理: 内存管理的开始,首先我们要梳理下,为什么要管理内存,像街道上的每个建筑都有他的地址一样,在电脑里, 每个数据也都有它存放的空间,每个空间都和它的地址一一对应。我们建...

0_0Loong ⋅ 2015/05/24 ⋅ 0

Objective-C 和 Core Foundation 对象相互转换的内存管理总结

一、非ARC的内存管理 倘若不使用ARC,手动管理内存,思路比较清晰,使用完,release转换后的对象即可。 //NSString 转 CFStringRef CFStringRef aCFString = (CFStringRef) [[NSString alloc...

木木情深 ⋅ 2014/02/19 ⋅ 0

InnoDB内存管理源码剖析

InnoDB的内存管理分为3层。1、在底层InnoDB创建一个通用内存池,负责为系统提供小块内存,另外InnoDB还创建缓冲池,可以为系统提供更大块的内存。两者都是向系统申请内存,只申请一次。其中,...

jzzlee ⋅ 2016/05/04 ⋅ 0

操作系统基本概念

一、基本概念 进程:对CPU使用的抽象 虚拟内存:对内存的抽象 文件系统:对磁盘的抽象 设计思想: (1)分层 (2)内核+模块化 1、并发 (1)流水线:指令级别的并发 指令读取-->指令译码-->...

xixicat ⋅ 2014/05/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部