nbsp; try{ // 分配内存块 默认是64个m_nallocsize.
pnewblock = cplex::create(m_pblocks, m_nblocksize, m_nallocsize);
}catch_all(e){
...异常
}end_catch_all
// 下面的代码是将内存块压入m_pnodefree链表中待用。
cnode* pnode = (cnode*)pnewblock->data();
(byte*&)pnode += (m_nallocsize * m_nblocksize) - m_nallocsize;
for (int i = m_nblocksize-1; i >= 0; i--, (byte*&)pnode -= m_nallocsize)
{
pnode->pnext = m_pnodefree;
m_pnodefree = pnode;
}
}
// 这两句是弹出一块内存给调用者使用。
void* pnode = m_pnodefree;
m_pnodefree = m_pnodefree->pnext;
...
return pnode;
}
/*
当调用者调用free时,只是将这块内存重新压入m_pnodefree链表中
并非释放,而是标志为可用块以待后用。
*/
void cfixedalloc::free(void* p)
{
if (p != null)
{
entercriticalsection(&m_protect);
cnode* pnode = (cnode*)p;
pnode->pnext = m_pnodefree;
m_pnodefree = pnode;
leavecriticalsection(&m_protect);
}
}
void cfixedalloc::freeall()
{
entercriticalsection(&m_protect);
m_pblocks->freedatachain();
m_pblocks = null;
m_pnodefree = null;
leavecriticalsection(&m_protect);
}
/*
在析构函数中 调用freeall进行释放内存
*/
cfixedalloc::~cfixedalloc()
{
freeall();
deletecriticalsection(&m_protect);
}
/*
mfc/include/afxplex_.h
*/
struct cplex // warning variable length structure
{
cplex* pnext;
void* data() { return this+1; }
static cplex* pascal create(cplex*& head, uint nmax, uint cbelement);
void freedatachain(); // free this one and links
};
/*
mfc/src/plex.cpp
*/
cplex* pascal cplex::create(cplex*& phead, uint nmax, uint cbelement)
{
cplex* p = (cplex*) new byte[sizeof(cplex) + nmax * cbelement];
p->pnext = phead;
phead = p; // 加入链表
return p;
}
void cplex::freedatachain() // free this one and links
{
cplex* p = this;
while (p != null){
byte* bytes = (byte*) p;
cplex* pnext = p->pnext;
delete[] bytes;
p = pnext;
}
}
============================================================================
现在我们用一个实例来看一下在release版本下的实际内存动作
以分配10000个 含有"abcdefghijklmnopqrstuvwxyz"串的cstring数组
cstring * strarray[10000];
for( int =0;i < 10000; i++ )
strarray[i] = new cstring("abcdefghijklmnopqrstuvwxyz");
因为字符串小于64所以调用了_afxalloc64::alloc;
----------------------------------------------------------------
_afxalloc64在strcore.cpp中被定义如下:
afx_static cfixedalloc _afxalloc64(round4(65*sizeof(tchar)+sizeof(cstringdata)));
在ansi版本下 sizeof(tchar) = 1
sizeof( cstrgindata ) = 12;
65*sizeof(tchar)+sizeof(cstringdata) = 77;
round4定义用下,将之圆整为4的倍数,
#define round(x,y) (((x)+(y-1))&~(y-1))
#define round4(x) round(x, 4)
所以
_afxalloc64(round4(65*sizeof(tchar)+sizeof(cstringdata))) 实际上
宏展开最终为
extern cfixedalloc _afxalloc64( 80,64);
----------------------------------------------------------------
在cplex中分配池的大小
sizeof(cplex) + nmax * cbelement = 4+80*64 = 5124 byte.
因为10000不是64的整数倍 = 要分配157个池
实际分配内存 = 157*5124 = 804468 byte = 804kb.
释放cstring对象
for( int =0;i < 10000; i++ )
delete strarray[i];
此时cstring 的调用_afxalloc64.free.
由cfixedalloc::free的实现可知此时并没有真正释放内存,只是将这该块重新加入m_pnodefree链表中待用.
因为cfixedalloc释放内存操作是在析构函数调用,而_afxalloc64是被定义为全局对象.它的析构函数要到程序退出才能被调用.
所以cfixedall