windows核心编程---堆

-堆
系统内部,堆就是一块预订的地址空间区域。刚开始,区域内的大部分页面没有调拨物理存储器。随着不断中堆中分配内存,堆管理器会给堆调拨越来越多的物理存储器。物理存储器从页交换文件中分配的。释放堆中内存块时,堆管理器会撤销已调拨的物理存储器。

-进程的默认堆
1.进程初始化时,系统会在进程的地址空间中创建一个堆。称为进程的默认堆。默认的地址空间区域大小1MB。
创建应用时,可用/HEAP改变默认大小。
/HEAP:reserve[, commit]

2.许多windows函数用到了进程的默认堆,且应用有许多线程同时调用各种windows函数。故,对默认堆的访问须依次进行。
系统保证,一次只让一个线程从默认堆分配或释放内存块。

-堆
一个进程可有多个堆。
默认堆是在进程开始运行前由系统自动创建的,在进程终止后自动销毁。
每个堆都有一个用来标识自己的堆句柄,所有分配和释放内存块的堆函数都会在参数中用到这个堆句柄。

// 得到进程默认堆的句柄
HANDLE GetProcessHeap();

-自定义堆
1.创建

// 预订地址空间+调拨区域内一小块
HANDLE WINAPI HeapCreate(
// HEAP_NO_SERIALIZE  取消堆多线程保护,由开发人员自行实现多线程保护机制
// HEAP_GENERATE_EXCEPTIONS 在堆中分配内存失败时,抛出异常
// HEAP_CREATE_ENABLE_EXECUTE 在堆中存放可执行代码
// 0无特殊要求,传0
  _In_ DWORD  flOptions,
 // 初始调拨块大小
  _In_ SIZE_T dwInitialSize,
 // > 0,预订区域大小
 // 区域可变。
  _In_ SIZE_T dwMaximumSize
);

自定义堆实现多线程保护支持

BOOL WINAPI HeapLock(
  _In_ HANDLE hHeap
);
BOOL WINAPI HeapUnlock(
  _In_ HANDLE hHeap
);

未指定HEAP_NO_SERIALIZE 标志,对堆的访问会依次进行,使多线程从同一个堆分配和释放内存块,也不会存在堆数据被破坏。

2.从堆中分配内存

LPVOID WINAPI HeapAlloc(
  _In_ HANDLE hHeap,
 // HEAP_GENERATE_EXCEPTIONS 如果要求的大小太大了或其他原因导致操作失败,触发异常
 // HEAP_NO_SERIALIZE 本次操作不需要多线程下互斥保护
 // HEAP_ZERO_MEMORY 堆中本次调拨内存初始值为0
  _In_ DWORD  dwFlags,
 //  要求从堆中分配的字节数
  _In_ SIZE_T dwBytes
)

BOOL WINAPI HeapFree(
  _In_ HANDLE hHeap,
  // 0
  // HEAP_NO_SERIALIZE 本次操作不需要多线程下互斥保护
  _In_ DWORD  dwFlags,
  _In_ LPVOID lpMem
);

LPVOID WINAPI HeapReAlloc(
  _In_ HANDLE hHeap,
  // HEAP_GENERATE_EXCEPTIONS 如果要求的大小太大了或其他原因导致操作失败,触发异常
  // HEAP_NO_SERIALIZE 本次操作不需要多线程下互斥保护
  // HEAP_REALLOC_IN_PLACE_ONLY 新调拨块必须续着原有块
  // HEAP_ZERO_MEMORY 
新块中超出原始块部分内容为0
  _In_ DWORD  dwFlags,
  // 指向原始块
  _In_ LPVOID lpMem,
  // 新的大小
  _In_ SIZE_T dwBytes
);

3.获得堆内块大小

SIZE_T WINAPI HeapSize(
  _In_ HANDLE  hHeap,
  // 0
  // HEAP_NO_SERIALIZE 
  _In_ DWORD   dwFlags,
  _In_ LPCVOID lpMem
);

4.销毁

BOOL WINAPI HeapDestroy(
// 撤销区域内所有已调拨操作+撤销预订的区域
  _In_ HANDLE hHeap
);

进程的默认堆由进程终止前自动销毁,不允许通过HeapDestroy销毁。

5.其它堆函数

DWORD WINAPI GetProcessHeaps(
  _In_  DWORD   NumberOfHeaps,
  _Out_ PHANDLE ProcessHeaps
);

// 验证堆未被破坏
BOOL WINAPI HeapValidate(
  _In_     HANDLE  hHeap,
  // HEAP_NO_SERIALIZE 没有多线程互斥
  _In_     DWORD   dwFlags,
  // NULL验证整个堆
  // 非NULL,验证堆内此块
  _In_opt_ LPCVOID lpMem
);

// 返回最大可用堆内块大小
SIZE_T WINAPI HeapCompact(
  _In_ HANDLE hHeap,
  _In_ DWORD  dwFlags
);

// 多线程保护堆,在堆访问函数内部调用此两个函数
// 锁定堆,堆被锁定,进程内其它线程不可用
BOOL WINAPI HeapLock(
  _In_ HANDLE hHeap
);

// 解除锁定
BOOL WINAPI HeapUnlock(
  _In_ HANDLE hHeap
);

// 枚举堆内的块
// 初始:lpEntry的lpData为NULL,每枚举成功一次,返回NULL。lpEntry被填充枚举的块信息。继续用此lpEntry执行调用,接着被填充下一块信息。枚举结束返回FALSE。
// 枚举开始,一般用HeapLock锁定堆。
// 枚举结束,一般用HeapUnlock解除锁定。
BOOL WINAPI HeapWalk(
  _In_    HANDLE               hHeap,
  _Inout_ LPPROCESS_HEAP_ENTRY lpEntry
);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值