堆栈

——Windows核心编程学习手札之十八

堆栈可以用来分配许多较小的数据块,可以不考虑分配粒度和页面边界之类的问题,但分配和释放内存块的速度比其他机制要慢,并且无法直接控制物理存储器的提交和回收。堆栈是保留的地址空间的一个区域,开始时,保留区域中的大多数页面没有被提交物理存储器,当从堆栈中进行越来越多的内存分配时,堆栈管理器将把更多的物理存储器提交给堆栈,物理存储器总是从系统的页文件中分配的,当释放堆栈中的内存块时,堆栈管理器将收回这些物理存储器。

进程初始化时,系统在进程的地址空间中创建一个堆栈,称为进程的默认堆栈,默认大小是1MB,但系统可以扩大进程的默认堆栈,使它大于其默认值,当创建应用程序时,可以使用/HEAP链接开关,改变堆栈的1MB默认区域大小。/HEAP链接开关的句法:

/HEAP:reserve[.commit]

可通过调用GetProcessHeap函数获取进程默认堆栈的句柄:

HANDLE GetProcessHeap();

除进程的默认堆栈外,可以在进程的地址空间中创建辅助堆栈,基于保护组件、更加有效地进行内存管理、进行本地访问、减少线程同步的开销、迅速释放等原因,需要创建辅助堆栈。线程调用HeapCreate函数可创建辅助堆栈:

HANDLE HeapCreate(

DWORD fdwOptions,

SIZE_T dwInitialSize,

SIZE_T dwMaximumSize);

第一个参数fdwOptions用于修改如何在堆栈上执行各种操作,可以设定0、HEAP_NO_SERIALIZE、HEAP_GENERATE_EXCEPTIONS或者组合标志。按照默认设置,堆栈将顺序访问自己,这样多个线程就能够分配和释放堆栈中的内存块而不至于破坏堆栈,但试图从堆栈中分配一个内存块时,HeapAlloc函数必须执行下列操作:

1)遍历分配的和释放的内存块的链接表;

2)寻找一个空闲内存块的地址;

3)通过将空闲内存块标记为“已分配”分配新内存块;

4)将新内存块添加给内存块链接表;

从堆栈中分配内存块,调用HeapAlloc函数:

PVOID HeapAlloc(

HANDLE hHeap,

DWORD fdwFlags,

SIZE_T dwBytes);

第一个参数hHeap用于标识分配的内存块来自的堆栈的句柄,dwBytes参数用于设定从堆栈中分配的内存块的字节数。

调用HeapReAlloc函数来改变内存块的大小:

PVOID HeapReAlloc(

HANDLE hHeap,

DWORD fdwFlags,

PVOID pvMem,

SIZE_T dwBytes);

当内存块分配后,可调用HeapSize函数来检索内存块的实际大小:

SIZE_T HeapSize(

HANDLE hHeap,

DWORD fdwFlags,

LPCVOID pvMem);

参数hHeap用于标识堆栈,参数pvMem用于指明内存块的地址,参数fdwFlags既可以是0,也可以是HEAP_NO_SERIALIZE。

当不再需要内存块时,可以调用HeapFree函数将其释放:

BOOL HeapFree(

HANDLE hHeap,

DWORD fdwFlags,

PVOID pvMem);

HeapFree函数用于释放内存块,如运行成功,则返回TRUE。

如果应用程序不再需要它创建的堆栈,可通过调用HeapDestroy函数将其撤消:

BOOL HeapDestroy(HANLDE hHeap);

调用HeapDestroy函数可以释放堆栈中包含的所有内存块,也可以将堆栈占用的物理存储器和保留的地址空间区域重新返回给系统。

堆栈——Windows核心编程学习手札之十八相关推荐

  1. 线程的堆栈——Windows核心编程学习手札之十六

    线程的堆栈 --Windows核心编程学习手札之十六 系统会在进程的地址空间内保存一些区域,同时也会在进程地址空间内为线程的堆栈保留区域.线程都有自己的堆栈,创建时,系统就保留一个堆栈空间区域,并将相 ...

  2. 在应用程序中使用虚拟内存——Windows核心编程学习手札之十五

    在应用程序中使用虚拟内存 --Windows核心编程学习手札之十五 Windows提供了3种进行内存管理的方法: 1)  虚拟内存,最适合用来管理大量对象或结构数组: 2)  内存映射文件,最适合用来 ...

  3. DLL基础——Windows核心编程学习手札之十九

    DLL基础 --Windows核心编程学习手札之十九 Windows API中的所有函数都包含在DLL中,3个最重要的DLL是Kernel32.dll,它包含用于管理内存.进程和线程的各个函数:Use ...

  4. 虚拟内存——Windows核心编程学习手札之十四

    虚拟内存 --Windows核心编程学习手札之十四 系统信息 有些操作系统的值是根据主机而定的,如页面大小.分配粒度大小等,这些值不用硬编码形式,进程初始化时应检索这些值以使用.函数GetSystem ...

  5. 异常处理程序和软件异常——Windows核心编程学习手札之二十四

    异常处理程序和软件异常 --Windows核心编程学习手札之二十四 CPU负责捕捉无效内存访问和用0除一个数值这种错误,并相应引发一个异常作为对错误的反应,CPU引发的异常称为硬件异常(hardwar ...

  6. 窗口消息——Windows核心编程学习手札之二十六

    窗口消息 --Windows核心编程学习手札之二十六 Windows允许一个进程至多建立10000个不同类型的用户对象(user object):图符.光标.窗口类.菜单.加速键表等,当一个线程调用一 ...

  7. 未处理异常和C++异常——Windows核心编程学习手札之二十五

    未处理异常和C++异常 --Windows核心编程学习手札之二十五 当一个异常过滤器返回EXCEPTION_CONTINUE_SEARCH标识符时是告诉系统继续上溯调用树,寻找另外的异常过滤器,但当每 ...

  8. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  9. DLL的高级操作技术——Windows核心编程学习手札之二十

    DLL的高级操作技术 --Windows核心编程学习手札之二十 显示加载DLL模块: HINSTANCE LoadLibrary(PCTSTR pszDLLPathName); HINSTANCE L ...

最新文章

  1. 设置UILabel可变高度(根据文本内容自动适应高度)
  2. Linux在文件第一行添加字符,使用shell命令给文件中每一行的前面、后面、指定列添加字符...
  3. Django contenttypes 应用
  4. eclipse安装Freemaker IDE插件
  5. smart模版学习笔记一
  6. 如何下载python模块_python中模块包的离线下载教程
  7. Java解决找不到主类或者无法加载主类
  8. 【编译原理笔记08】语法制导翻译:语法制导定义,SSD的求值顺序,S属性定义与L属性定义
  9. 11g oracle 客户端驱动_oracle 11g 数据库驱动包
  10. FPGA学习笔记-IP核-FIFO
  11. 去掉word中页眉上方的一条线
  12. 非安装版 Python 安装 PIP
  13. [Noi online-j]T1 切蛋糕
  14. java实现京东云第三方登录
  15. Failed to execute ‘btoa‘ on ‘Window‘: The string to be encoded contains characters outside of the La
  16. 硬盘提示格式化的解决办法:
  17. 如何显示在网页中显示阿拉伯语言
  18. 幂等和非幂等的关系与区别
  19. 学物理赶不上计算机,高二上学期物理为何这么难?
  20. Convert hex to base64

热门文章

  1. PHP未定义名称的方法,PHP:“调用未定义的方法”......但方法是否已定义?
  2. eve模拟器华为镜像_EVE-NG简单入门介绍
  3. linux设置进程优先级,Linux线程属性及优先级设置
  4. json mysql 字段 默认值_MySQL中的JSON类型
  5. Apache开启GZIP压缩功能方法
  6. Linux文件系统属性权限chattr与lsattr命令
  7. Spring Boot2.0之 整合Redis集群
  8. 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)
  9. GitLab 502问题的解决
  10. Android开发7——android.database.CursorIndexOutOfBoundsException:Index -1 requested