进程的默认堆与自建堆
来源:互联网 发布:多益网络线上笔试题目 编辑:程序博客网 时间:2024/05/29 23:23
最近去了一次面试,面试官问道这个进程的自建堆和默认堆的相关问题,我当时感觉答的并不是很好,这时候我决定好好整理一下相关知识跟大家分享。
进程默认堆:
Windows许多重要的函数都用Unicode字符和Unicode字符串来执行它们所有的操作。如果我们调用的是一个函数的ANSI版本,那么该函数的ANSI版本必须把ANSI字符串转换为Unicode字符串,然后再调用同一个函数的Unicode版本。为了转换字符串,ANSI版本的函数需要分配一块内存来保存Unicode版本的字符串,这块内存就是从进程的默认堆中分配的。默认堆大小一般为1M,可以在编译器设置/HEAP。
进程自建堆:
为什么要创建额外的堆:
1.对组件进行有效的保护
2.更有效的内存管理
3.使内存访问局部化
4.避免线程的同步开销
5.快速释放
1.对组件进行保护
举个栗子:有一个链表和一个二叉树都需要保存在同一个堆中,这会使两种结构混合,假如链表中的某个节点出错覆盖他下边的某块内存,就可能把二叉树结构破坏,这会导致定位出错很难,于是把两种结构放到两个堆中,这种可能性就会小很多。
2.更有效的内存管理:
每个堆保证相同的结构会使内存分配更为合理。再举上一个栗子,链表每个节点大小为24字节,二叉树每个节点32字节,现在链表释放了2个节点,这时有了48字节的空间,但是很有可能这两块内存不连续。而没法给二叉树分配一个节点的空间。如此操作,会使堆内内存碎片化。
3.使内存访问局部化
我们知道系统在访问内存的时候会产生页交换,当系统把一个内存页换入到磁盘中,再从磁盘中换出一个内存页时,这种消耗是十分巨大的。于是,把相同的节点放在一个内存堆中就显得尤为重要了。继续举栗子,当我们一个堆中只保存链表节点,或者只保存二叉树节点,这个时候内存很有可能分配到邻近一块儿内存中,这时候我们遍历节点就不需要再进行页交换了。但是两个结构混用的话,很有可能看似相邻的两个节点其实在两个页交换文件中,如果运气差,有可能进行一次遍历,系统需要多次进行页交换,大大降低了效率。
4.避免线程同步的开销
在默认情况下,系统中线程对堆的访问是依次进行的,如果你自己创建了堆,系统将不会用额外代码来保证线程的安全性,就会在一定程度上减小系统的消耗,不过这时候对堆的内存操作将有我们自己进行,系统将不再管理。
5.快速释放
如果我们创建一个堆来存放数据,我们在销毁数据的时候可以仅仅将整个堆的内存释放,而不必一个个节点去释放,大大加快了释放内存的效率。
如何创建额外的堆
我们可以调用HeapCreate函数来创建额外的堆。函数原型如下:
HANDLEWINAPIHeapCreate( _In_ DWORD flOptions, //表示对堆的操作应该如何进行 _In_ SIZE_T dwInitialSize, //表示一开始系统调拨给堆的字节数,如果需要系统会将这个值向上取整到CPU页面的整数倍 _In_ SIZE_T dwMaximumSize //向上取整最大字节数 );
0 0
- 进程的默认堆与自建堆
- 进程线程与栈、堆的关系
- 进程线程与栈 堆的关系
- Window的进程堆
- Linux进程的堆
- experiment : 在私有堆和默认进程堆中, 测试能分配的堆空间总和, 每次能分配的最大堆空间
- 栈、堆、进程堆
- 链接、装载与库——进程的堆
- 堆的构建与堆排序
- Java的堆与非堆内存
- 最小堆与最大堆的实现
- 堆的建立与堆排序
- 最大堆与最小堆的实现
- 八.堆与堆的构建
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 在KEIL中选一款你爱的字体
- 初窥Linux 之 我最常用的20条命令
- 图书管理系统主界面
- 训练23-HTML 使用#符合设置固定链接
- 阿里巴巴常考面试题及汇总答案
- 进程的默认堆与自建堆
- 图书管理系统学生信息界面
- Python源码剖析[16] —— Pyc文件解析
- 训练24-HTML 为图片设置超链接
- caffe学习笔记17-find-tuning微调学习
- 1068. 万绿丛中一点红(20)乙级
- 转:设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- Linux的一些基础常见命令
- JAVA 在线预览