博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 封装私有堆(Private Heap)
阅读量:6472 次
发布时间:2019-06-23

本文共 8741 字,大约阅读时间需要 29 分钟。

  Private Heap 是 Windows 提供的一种内存内存机制,对于那些需要频繁分配和释放动态内存的应用程序来说,Private Heap 是提高应用程序性能的一大法宝,使用它能降低 new / malloc 的调用排队竞争以及内存空洞。Private Heap 的原理及应用的资料很多,这里就不一一介绍了,常用的 Private Heap API 有以下几个,具体介绍请参考帮助文档:

HeapCreate(); HeapDestroy(); HeapAlloc(); HeapReAlloc(); HeapSize(); HeapFree(); HeapCompact();

  

  由于是 C 风格的 API,使用起来比较繁琐,因此本座在闲暇之余用 C++ 对这些 API 进行了封装,主要包括两个类:

  • CPrivateHeap:自动创建和销毁进程私有堆,每一个该类的对象都代表一个私有堆,所以该类对象的特点是: 一般生命周期都比较长,通常作为全局对象, 其他类的静态成员对象或者一些长生命周期类对象的成员。
  • CPrivateHeapBuffer<T>:在私有堆中自动分配和释放指定大小的内存,一般用于在函数体内分配和释放局部作用域的堆内存,从而避免对 CPrivateHeap::Alloc() 和 CPrivateHeap::Free() 的调用。
#pragma once class CPrivateHeap {
public: enum EnCreateOptions {
CO_DEFAULT = 0, CO_NO_SERIALIZE = HEAP_NO_SERIALIZE, CO_GENERATE_EXCEPTIONS = HEAP_GENERATE_EXCEPTIONS, CO_NOSERIALIZE_GENERATEEXCEPTIONS = HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS }; enum EnAllocOptions {
AO_DEFAULT = 0, AO_ZERO_MEMORY = HEAP_ZERO_MEMORY, AO_NO_SERIALIZE = HEAP_NO_SERIALIZE, AO_GENERATE_EXCEPTIONS = HEAP_GENERATE_EXCEPTIONS, AO_ZEROMEMORY_NOSERIALIZE = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, AO_ZEROMEMORY_GENERATEEXCEPTIONS = HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, AO_NOSERIALIZE_GENERATESEXCEPTIONS = HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS, AO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS }; enum EnReAllocOptions {
RAO_DEFAULT = 0, RAO_ZERO_MEMORY = HEAP_ZERO_MEMORY, RAO_NO_SERIALIZE = HEAP_NO_SERIALIZE, RAO_GENERATE_EXCEPTIONS = HEAP_GENERATE_EXCEPTIONS, RAO_REALLOC_IN_PLACE_ONLY = HEAP_REALLOC_IN_PLACE_ONLY, RAO_ZEROMEMORY_NOSERIALIZE = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, RAO_ZEROMEMORY_GENERATEEXCEPTIONS = HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, RAO_ZEROMEMORY_REALLOCINPLACEONLY = HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY, RAO_NOSERIALIZE_GENERATESEXCEPTIONS = HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS, RAO_NOSERIALIZE_REALLOCINPLACEONLY = HEAP_NO_SERIALIZE | HEAP_REALLOC_IN_PLACE_ONLY, RAO_GENERATESEXCEPTIONS_REALLOCINPLACEONLY = HEAP_GENERATE_EXCEPTIONS | HEAP_REALLOC_IN_PLACE_ONLY, RAO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS, RAO_ZEROMEMORY_NOSERIALIZE_REALLOCINPLACEONLY = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE | HEAP_REALLOC_IN_PLACE_ONLY, RAO_ZEROMEMORY_GENERATESEXCEPTIONS_REALLOCINPLACEONLY = HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS | HEAP_REALLOC_IN_PLACE_ONLY, RAO_NOSERIALIZE_GENERATESEXCEPTIONS_REALLOCINPLACEONLY = HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS | HEAP_REALLOC_IN_PLACE_ONLY, RAO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS_REALLOCINPLACEONLY = HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS | HEAP_REALLOC_IN_PLACE_ONLY }; enum EnSizeOptions {
SO_DEFAULT = 0, SO_NO_SERIALIZE = HEAP_NO_SERIALIZE }; enum EnFreeOptions {
FO_DEFAULT = 0, FO_NO_SERIALIZE = HEAP_NO_SERIALIZE }; enum EnCompactOptions {
CPO_DEFAULT = 0, CPO_NO_SERIALIZE = HEAP_NO_SERIALIZE }; public: PVOID Alloc(DWORD size, EnAllocOptions options = AO_DEFAULT) {
return ::HeapAlloc(m_heap, options, size);} PVOID ReAlloc(PVOID pvmem, DWORD size, EnReAllocOptions options = RAO_DEFAULT) {
return ::HeapReAlloc(m_heap, options, pvmem, size);} DWORD Size(PVOID pvmem, EnSizeOptions options = SO_DEFAULT) {
return (DWORD)::HeapSize(m_heap, options, pvmem);} BOOL Free(PVOID pvmem, EnFreeOptions options = FO_DEFAULT) {
return ::HeapFree(m_heap, options, pvmem);} DWORD Comapct(EnCompactOptions options = CPO_DEFAULT) {
return (DWORD)::HeapCompact(m_heap, options);} BOOL IsValid() {
return m_heap != NULL;} public: CPrivateHeap(EnCreateOptions options = CO_DEFAULT, DWORD initsize = 0, DWORD maxsize = 0) {m_heap = ::HeapCreate(options, initsize, maxsize);} ~CPrivateHeap() {
if(IsValid()) ::HeapDestroy(m_heap);} private: CPrivateHeap(const CPrivateHeap&); CPrivateHeap operator = (const CPrivateHeap&); private: HANDLE m_heap; }; template
class CPrivateHeapBuffer {
public: CPrivateHeapBuffer( CPrivateHeap& heap, DWORD size = 0, CPrivateHeap::EnAllocOptions allocoptions = CPrivateHeap::AO_DEFAULT, CPrivateHeap::EnFreeOptions freeoptions = CPrivateHeap::FO_DEFAULT) : m_hpPrivate(heap) , m_opFree(freeoptions) {
ASSERT(m_hpPrivate.IsValid()); m_pvMemory = (T*)m_hpPrivate.Alloc(size * sizeof(T), allocoptions); } ~CPrivateHeapBuffer() {m_hpPrivate.Free(m_pvMemory, m_opFree);} T* ReAlloc(DWORD size, CPrivateHeap::EnReAllocOptions options = CPrivateHeap::RAO_DEFAULT) {
return m_pvMemory = (T*)m_hpPrivate.ReAlloc(m_pvMemory, size * sizeof(T), options);} DWORD Size(CPrivateHeap::EnSizeOptions options = CPrivateHeap::SO_DEFAULT) {
return m_hpPrivate.Size(m_pvMemory, options);} operator T* () const {
return m_pvMemory;} private: CPrivateHeapBuffer(const CPrivateHeapBuffer&); CPrivateHeapBuffer operator = (const CPrivateHeapBuffer&); private: CPrivateHeap& m_hpPrivate; T* m_pvMemory; CPrivateHeap::EnFreeOptions m_opFree; }; typedef CPrivateHeapBuffer
CPrivateHeapByteBuffer; typedef CPrivateHeapBuffer
CPrivateHeapStrBuffer;

 

  上述代码看起来挺复杂,但使用起来却是异常简单的,请看下面的使用示例:

// 全局可见的 Heap CPrivateHeap g_heap; class MyClass {
private: // 与类实例生命周期一致的 Heap CPrivateHeap m_heap; // 仅类内部可见的 Heap static CPrivateHeap sm_heap; public: void test_m_eap() {
// 无需显式释放堆内存 CPrivateHeapStrBuffer buff(m_heap, 32); lstrcpy(buff, _T("失败乃成功之母")); DWORD size = buff.Size(); buff.ReAlloc(40 * sizeof(TCHAR)); size = buff.Size(); std::cout << (TCHAR*)buff << '\n'; } static void test_sm_eap() {
CPrivateHeapStrBuffer buff(sm_heap, 32); lstrcpy(buff, _T("失败乃成功之母")); DWORD size = buff.Size(); buff.ReAlloc(40 * sizeof(TCHAR)); size = buff.Size(); std::cout << (TCHAR*)buff << '\n'; } }; void test_g_heap() {
// 如果不使用 CPrivateHeapBuffer
来封装堆内存 ASSERT(g_heap.IsValid()); TCHAR* pch = (TCHAR*)g_heap.Alloc(32 * sizeof(TCHAR)); lstrcpy(pch, _T("失败乃成功之母")); DWORD size = g_heap.Size(pch); g_heap.ReAlloc(pch, 40 * sizeof(TCHAR)); size = g_heap.Size(pch); std::cout << pch << '\n'; // 需要显式释放堆内存 g_heap.Free(pch); } int _tmain(int argc, _TCHAR* argv[]) {
test_g_heap(); MyClass::test_sm_eap(); MyClass c; c.test_m_eap(); return 0; }

 

转载地址:http://gvpko.baihongyu.com/

你可能感兴趣的文章
eBay通过事件溯源实现持续交付
查看>>
Google开源了Abseil,为C++和Python开发提供支持
查看>>
亚马逊发布新的AWS Step Functions集成
查看>>
Scala在挖财的应用实践
查看>>
区块链和数据科学:如果同时应用这两种技术,将会实现什么?
查看>>
天机阁——全链路跟踪系统设计与实现
查看>>
跳一跳作弊器上榜!GitHub 2018年十大新开源项目揭晓
查看>>
如何通过解决精益问题提高敏捷团队生产力
查看>>
机器学习工程师职位正在消失
查看>>
Docker再曝安全漏洞,这次是PWD的问题
查看>>
如何利用PostgreSQL的延迟复制实现灾备
查看>>
ChaosConf 2018:混沌实验的演变
查看>>
微软对macOS和Linux开放量子开发工具集
查看>>
区块链安全:2019年我们走了多远?
查看>>
聪明的头脑+有趣的灵魂,揭秘腾讯云最暖智能酒店解决方案
查看>>
通过XAML Islands使Windows桌面应用程序现代化
查看>>
老肖有话说:雾霾天带你看清Crane技术实现之路
查看>>
Bootstrap 之 Metronic 模板的学习之路 - (7)GULP 前端自动化工具
查看>>
ES6 + Webpack + React + Babel 如何在低版本浏览器上愉快的玩耍(下)
查看>>
Vuex使用总结
查看>>