CvMemStorageAlloc的作用就是在存储器中分配size个字节的内存,并把指针返回
分配过程可以看源代码
源代码
/* Allocate continuous buffer of the specified size in the storage: */
CV_IMPL void*
cvMemStorageAlloc( CvMemStorage* storage, size_t size )
{
schar *ptr = 0;
if( !storage )
CV_Error( CV_StsNullPtr, "NULL storage pointer" );
if( size > INT_MAX )
CV_Error( CV_StsOutOfRange, "Too large memory block is requested" );
assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
if( (size_t)storage->free_space < size )
{
size_t max_free_space = cvAlignLeft(storage->block_size - sizeof(CvMemBlock), CV_STRUCT_ALIGN);
if( max_free_space < size )
CV_Error( CV_StsOutOfRange, "requested size is negative or too big" );
icvGoNextMemBlock( storage );
}
ptr = ICV_FREE_PTR(storage);
assert( (size_t)ptr % CV_STRUCT_ALIGN == 0 );
storage->free_space = cvAlignLeft(storage->free_space - (int)size, CV_STRUCT_ALIGN );
return ptr;
}
从这行代码可以看出
if( (size_t)storage->free_space < size )
存储器CvMemStorage* storage中有多个存储块,当前存储块top中的剩余空间free_space满足size大小的分配,则直接分配,再调整free_space大小,并返回指针。如果不满足,则调用执行icvGoNextMemBlock( storage );调用后top块为一个新的存储块,肯定满足分配size字节。
下面查看icvGoNextMemBlock的源代码
icvGoNextMemBlock的作用就是查找下一块存储块。
/* Moves stack pointer to next block.
If no blocks, allocate new one and link it to the storage: */
static void
icvGoNextMemBlock( CvMemStorage * storage )
{
if( !storage )
CV_Error( CV_StsNullPtr, "" );
if( !storage->top || !storage->top->next )
{
CvMemBlock *block;
if( !(storage->parent) )
{
block = (CvMemBlock *)cvAlloc( storage->block_size );//没有后续块或者甚至当前块也没有分配,也不是子块的话就只能alloc了;
}
else//有父存储器则从父存储器中取得。自己不用分配存储块
{
CvMemStorage *parent = storage->parent;
CvMemStoragePos parent_pos;
cvSaveMemStoragePos( parent, &parent_pos );
icvGoNextMemBlock( parent );//递归调用,最顶层父存储器分配存储块
block = parent->top;
cvRestoreMemStoragePos( parent, &parent_pos );
if( block == parent->top ) /* the single allocated block */
{
assert( parent->bottom == block );
parent->top = parent->bottom = 0;
parent->free_space = 0;
}
else
{
/* cut the block from the parent's list of blocks */
parent->top->next = block->next;
if( block->next )
block->next->prev = parent->top;
}
}
/* link block */
block->next = 0;
block->prev = storage->top;
if( storage->top )
storage->top->next = block;
else
storage->top = storage->bottom = block;
}
if( storage->top->next )//有后续块,就把后续块设置为top块。最终top块为新分配块
storage->top = storage->top->next;
storage->free_space = storage->block_size - sizeof(CvMemBlock);
assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
}