ATL Internals 2ed复习.chapter 3.ATL Memory Managers

A Review of Windows Memory Management

Windows有三种内存

stack 栈:用于分配本地变量,大小在编译时确定,分配与释放仅需移动栈指针

memory-mapped files 内存映射文件:不讨论

heap 堆:用于分配动态变量,大小在运行时确定,使用heap manager进行分配和回收

 

在Windows中,每个进程启动时会分配一个default heap,然后使用HeapCreate, HeapAlloc,HeapFree进行default heap的管理,访问default heap是线程安全的。

使用CRT库的函数可能会使用CRT heap,并且使用malloc和free来管理。

COM使用CoTaskMemAlloc和CoTaskMemFree来管理进程间Mashal,如[out]参数,在一个进程中创建,在另一个进程中销毁。

使用不同的堆模型,能够提高了并发性,并且减少换页。

 

The IAtlMemMgr Interface

__interface IAtlMemMgr {                        
public:                                         
    void* Allocate( size_t nBytes ) ;           
    void Free( void* p ) ;                      
    void* Reallocate( void* p, size_t nBytes ) ;
    size_t GetSize( void* p ) ;                 
};                                              

The Memory Manager Classes

ATL提供了5个Heap Manger classes

Memory Manager Class

Heap Functions Used

CComHeap

CoTaskMemAlloc, CoTaskMemFree, CoTaskMemRealloc, IMalloc::GetSize

CCRTHeap

malloc, free, realloc, _msize

CLocalHeap

LocalAlloc, LocalFree, LocalReAlloc, LocalSize

CGlobalHeap

GlobalAlloc, GlobalFree, GlobalReAlloc, GlobalSize

CWin32Heap

HeapAlloc, HeapFree, HeapReAlloc, HeapSize


例如:

class CComHeap :                                           
    public IAtlMemMgr {                                    
// IAtlMemMgr                                              
public:                                                    
    virtual void* Allocate( size_t nBytes ) {              
#ifdef _WIN64                                              
        if( nBytes > INT_MAX ) { return( NULL ); }         
#endif                                                     
        return( ::CoTaskMemAlloc( ULONG( nBytes ) ) );     
    }                                                      
    virtual void Free( void* p ) {                         
        ::CoTaskMemFree( p );                              
    }                                                      
    virtual void* Reallocate( void* p, size_t nBytes ) {   
#ifdef _WIN64                                              
        if( nBytes > INT_MAX ) { return( NULL ); }         
#endif                                                     
        return( ::CoTaskMemRealloc( p, ULONG( nBytes ) ) );
    }                                                      
    virtual size_t GetSize( void* p ) {                    
        CComPtr< IMalloc > pMalloc;                        
        ::CoGetMalloc( 1, &pMalloc );                      
        return( pMalloc->GetSize( p ) );                   
    }                                                      
};                                                         

 

注意,CWn32Heap与众不同,其使用Handle而不是进程堆

CWin32Heap()  :    m_hHeap( NULL ), m_bOwnHeap( false ) { }   
CWin32Heap( HANDLE hHeap )  :                                 
    m_hHeap( hHeap ),                                         
    m_bOwnHeap( false ) {                                     
    ATLASSERT( hHeap != NULL );                               
}                                                             
CWin32Heap( DWORD dwFlags, size_t nInitialSize,               
    size_t nMaxSize = 0 ) :                                   
    m_hHeap( NULL ),                                          
    m_bOwnHeap( true ) {                                      
    ATLASSERT( !(dwFlags&HEAP_GENERATE_EXCEPTIONS) );     
    m_hHeap = ::HeapCreate( dwFlags, nInitialSize, nMaxSize );
    if( m_hHeap == NULL ) { AtlThrowLastWin32(); }            
}                                                             

void Attach( HANDLE hHeap, bool bTakeOwnership ) {
    ATLASSERT( hHeap != NULL );                   
    ATLASSERT( m_hHeap == NULL );                 
    m_hHeap = hHeap;                              
    m_bOwnHeap = bTakeOwnership;                  
}                                                 
HANDLE Detach() {                                 
    HANDLE hHeap;                                 
                                                  
    hHeap = m_hHeap;                              
    m_hHeap = NULL;                               
    m_bOwnHeap = false;                           
                                                  
    return( hHeap );                              
}                                                 


应该避免下面:

// create an instance and allocate a heap
CWin32Heap heap(0,        // no exceptions, use thread-safe access
                4000,     // initial size
                0);       // no max size => heap grows as needed

// manually create a second heap
HANDLE hHeap = ::HeapCreate(0, 5000, 0);

// this is gonna get you in a "heap" of trouble!
heap.Attach(hHeap, false /* same result if true */ );


使用线程专用堆的例子:

DWORD g_dwTlsIndex;    // holds thread-local storage slot index
// g_dwTlsIndex = ::TlsAlloc() performed in other
// initialization code

// Create a private heap for use on this thread
// only => no synchronized access
CWin32Heap* pHeap = new CWin32Heap(HEAP_NO_SERIALIZE, 50000);

// Store the heap pointer in this thread's TLS slot
::TlsSetValue(g_dwTlsIndex, reinterpret_cast<void*>(
static_cast<IAtlMemMgr*>(pHeap)));

// ...

// Retrieve the heap pointer from TLS
pHeap = (IAtlMemMgr*)::TlsGetValue(g_dwTlsIndex);

// Create a new CStencil instance that uses the private heap
CStencil* pStencil = new CStencil(pHeap);


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值