堆是用来管理链表和村的最佳方式,堆始终是从页交换文件中分配。 优点:不必理会分配粒度和页面边界;缺点:分配和释放内存块的速度比其他方式慢。
进程有自己的默认堆1M,/HEAP改变,系统保证默认堆是线程安全的,许多windows函数用到默认堆。
额外堆:
1.对组件进行保护 //使问题局部化,一个堆中问题不影响另一个堆
2.更有效的内存管理
3.局部访问 //把相应的数据放一个堆,一次换入内存中,比数据分散多个页面效率高
4.避免线程同步的开销 //自己负责堆线程安全,如果单线程可以用HEAP_NO_SERIALIZE标志来分配堆
5.快速释放 //堆中多个内存块,直接释放堆而不用释放多个内存块
HeapCreate //HEAP_NO_SERIALIZE 使用些标志要保证线程安全,如用临界区,互斥量,信号量 //HEAP_GENERATE_EXCEPTIONS作用于堆中所有HeapAlloc
HeapAlloc //HEAP_GENERATE_EXCEPTIONS只作用于当前HeapAlloc
HeapReAlloc
HeapSize
HeapFree //释放内存块
HeapDestroy //销毁堆
如果传HEAP_NO_SERIALIZE参数自己保证线程安全,可用
HeapLock
HeapUnlock成对函数来线程同步
HeapAlloc,HeapSize,HeapFree之类的函数内部已经调用上面的两个函数。
//class.h
#pragma once
#include <Windows.h>
//通过一组s_hHeap s_uNumAllocsInHeap来实现一个类使用一个堆。
class SomeClass
{
public:
SomeClass(void);
~SomeClass(void);
void* operator new(size_t size);
void operator delete(void *p);
UINT GetBlocks();
private:
static HANDLE s_hHeap;
static UINT s_uNumAllocsInHeap;
int s_iMember;
};
//class.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void):s_iMember(s_uNumAllocsInHeap)
{
}
SomeClass::~SomeClass(void)
{
}
void* SomeClass::operator new(size_t size)
{
if( s_hHeap == NULL )
{
s_hHeap = HeapCreate(HEAP_NO_SERIALIZE,0,0);
if( s_hHeap == NULL )
return NULL;
}
void *p = HeapAlloc(s_hHeap,0,size);
if( p != NULL )
{
s_uNumAllocsInHeap++;
}
return p;
}
void SomeClass::operator delete(void *p)
{
if( HeapFree(s_hHeap,0,p) )
s_uNumAllocsInHeap--;
if(s_uNumAllocsInHeap == 0 )
{
if( HeapDestroy(s_hHeap) )
s_hHeap = NULL;
}
}
UINT SomeClass::GetBlocks()
{
return s_uNumAllocsInHeap;
}
HANDLE SomeClass::s_hHeap = NULL;
UINT SomeClass::s_uNumAllocsInHeap = 0;
//main.cpp
#include "SomeClass.h"
#include <iostream>
void wmain()
{
SomeClass *p1 = new SomeClass();
UINT uint1 = p1->GetBlocks();
SomeClass *p2 = new SomeClass();
UINT uint2 = p2->GetBlocks();
SomeClass *p3 = new SomeClass();
UINT uint3 = p3->GetBlocks();
delete p1;
delete p2;
UINT uintsss = p3->GetBlocks();
delete p3;
std::cout<<uint1<<" "<< uint2 << " " << uint3 << " " << uintsss << std::endl;
}