堆的使用

 

一、  堆的概述

从内部来讲,堆时保留的地址空间的一个区域,保留区域中大多数页面没有被提交物理存储器,当从堆中分配越来越多的内存时,堆管理器把更多的物理存储器提交给堆。物理存储器总是从系统的页文件中分配的。

当进程初始化时,系统在进程地址空间中创建一个堆,该堆称为进程的默认堆,该队地址空间区域的大小未 1M ,许多系统函数需要使用一些临时内存块,这些内存块时从进程的默认堆中分配的。

默认堆的访问是顺序进行的,基同一时间指允许一个线程对堆进行访问,保证了堆访问的互斥与同步。

二、  自定义堆的必要性

除了进程的默认堆之外,可以在进程的地址空间中创建一些辅助堆,辅助堆的创建将有助于提高系统的性能。

1、   保护组件

在一个堆中存放两种类型的数据时,若其中一个出现错误,很可能影响到另一个结构,如一个链表和一个二叉树存放在同一个堆中,他们的结点交叉存放,假如在修改链表中的某个结点时,错误的修改了节点的下一个内存地址,又恰巧下一个节点存储的是二叉树的一个结点,那么链表的错误将影响到二叉树。

若将链表和二叉树存放在不同的堆中,将大大减少上述错误。

2、   更有效的利用内存

当不同大小的结点占据相同的堆时,由于堆存储的不连续性,很可能释放了许多不连续的小的内存块,但不能满足一个较大的内存块的申请,若一个堆中存放的是相同大小的内存块,那么释放的内存块马上能够在下一次申请时分配出去。从而提高了内存的利用率。

3、   有利于进行本地访问

将同一种类型的数据存放在一个堆中,他们更又可能分配到同一个页面上,从而提高了数据的局部性,减少缺页概率。

4、   减少线程同步的开销

当确定进程为单线程时,在创建堆时可以告诉系统,不需要进行互斥与同步保护,从而减少线程同步的开销。

5、   迅速释放堆

将专用堆用于某些数据结构后,就可以释放整个堆,而不必显示释放堆中的每个内存块。

三、  使用辅助堆

1、   创建辅助堆

HANDLE HepaCreate(

           DWORD fdwOptions,                   /*如何在堆上执行各种操作*/

           SIZE_T dwInitialSize,           /*最初提交给堆的字节数*/

           SIZE_T dwMaximumSize);  /*堆的最大值,当值为0时表示能无限扩展*/

堆上执行的操作标识:

           HEAP_NO_SERIALIZE:不进行同步

           HEAP_GENERATE_EXCEPTIONS:当分配或重新分配堆中内存块失败时,引发异常

2、   从堆中分配内存

PVOID HeapAlloc(

           HANDLE hHeap,        /*堆句柄*/

           DWORD fdwFlags,     /*分配标识*/

           SIZE_T dwBytes);      /*从堆中分配的字节数*/

分配标识:

           HEAP_ZERO_MEMORY:分配完毕后用0初始化

3、   改变内存块的大小

PVOID HeapReAlloc(

           HANDLE hHeap,        /*要改变其大小的堆*/

           DWORD fdwFlags,     /*创建标识*/

           PVOID pvMem,          /*要改变其大小的内存块的地址*/

           SIZE_T dwBytes);      /*内存块的新的大小*/

4、   查看内存块的大小

SIZE_T HeapSize(

           HANDLE hHeap,        /*堆句柄*/

           DWORD fdwFlags,     /*0或者HEAP_NO_SERIALIZE*/

           LPCVOID pvMem);    /*内存块地址*/

5、   释放内存块

BOOL HeapFree(

           HANDLE hHead         ,        /*堆句柄*/

           DWORD fdwFlags,     /*0或者HEAP_NO_SERIALIZE*/

           PVOID pvMem);         /*内存块地址*/

6、   撤销堆

BOOL HeapDestroy(

HANDLE hHeap);       /*堆句柄*/

7、   获取默认堆句柄

HANDLE GetProcessHeap();

8、   获取进程中的所有堆

DWORD GetProcessHeaps(

           DWORD dwNumHeaps,      /*堆句柄数组大小*/

           PHANDLE pHeaps);            /*堆句柄数组*/

9、   检测堆的完整性

BOOL HeapVallidate(

           HANDLE hHeap,        /*堆句柄*/

           DWORD fdwFlags,     /*0或者HEAP_NO_SERIALIZE*/

           LPCVOID pvMem);    /*需要检测的内存块地址,当为NULL时检测堆中所有内存块*/

10、合并堆中空闲内存块

UINT HeapCompact(

           HANDLE hHeap,        /*堆句柄*/

           DWORD fdwFlags);    /*0或者HEAP_NO_SERIALIZE*/

11、堆的加锁与解锁

BOOL HeapLock(HANDLE hHeap);      /*堆句柄*/

BOOL HeapUnlock(HANDLE hHeap);  /*堆句柄*/

12、枚举堆中内存块

BOOL HeapWald(

           HANDLE hHeap,                                             /*堆句柄*/

           PPROCESS_HEAP_ENTRY pHeapEntry);

堆的使用:

#pragma once

#include <iostream>

#include <windows.h>

using namespace std;

 

/*从自定义堆中申请空间的模版类*/

template <class T>

class LinkNode

{

public:

     T node;

     LinkNode * proNode;

     LinkNode * nextNode;

     static HANDLE heap;

     static unsigned int numNode;

public :

     void * operator new(size_t size);

     void operator delete(void *p);

     void * ChangeClassSize();

};

 

template <class T>

HANDLE LinkNode<T>::heap = NULL;

 

template <class T>

unsigned int LinkNode<T>::numNode = 0;

 

template<class T>

void *LinkNode<T>::operator new(size_t size)

{

     if(heap == NULL)

     {

         /*创建自定义堆*/

         heap = HeapCreate(0, 0, 0);

         if(heap == NULL)

         {

              return NULL;

         }

     }

 

     /*从堆中分配内存块*/

     void * p = HeapAlloc(heap, 0, sizeof(LinkNode));

 

     if(p != NULL)

     {

         ++numNode;

     }

 

     return p;

}

 

template <class T>

void LinkNode<T>::operator delete(void *p)

{

     /*释放堆中的内存块*/

     if(HeapFree(heap, 0, p))

     {

         --numNode;

     }

 

     if(numNode == 0)

     {

         /*撤销自定义的堆*/

         if(HeapDestroy(heap))

         {

              heap = NULL;

         }

     }

}

 

#include <iostream>

using namespace std;

 

#include "LinkNode.h"

 

void main()

{

     LinkNode<int> *node = new LinkNode<int>();

     node->node = 5;

     cout << node->node << endl;

     node->ChangeClassSize();

     cout << node->node << endl;

 

     system("pause");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值