(7)cvMemStorageAlloc
該函數,首先判斷Storage的剩餘空間和待分配的空間的大小關係,若滿足分配條件就直接在對應的TOP塊中分配對應的空間,並且更改相關參數。如果待分配空間>剩餘空間,則調用函數icvGoNextMemBlock()對storage進行調整,然後再進行分配。
源碼:
- CV_IMPL void*
- cvMemStorageAlloc( CvMemStorage* storage, size_t size )
- {
- char *ptr = 0;
- CV_FUNCNAME( "cvMemStorageAlloc" );
- __BEGIN__;
- 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" );
- CV_CALL( 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 );
- __END__;
- return ptr;
- }
(8)icvGoNextMemBlock
該函數,如果Storage的storage->top->next!=0,則 將Storage的TOP塊指針移動到下一個Block塊上,然後設置好相關的參數,返回。 如果是新分配的Storage,其storage->top==0,若其也沒有Parent節點,那麼就給他分配一塊storage->block_size大小的空間
然後將其作爲該Storage的第一個Block,並設置相關的參數;若其有Parent節點,則在他的父節點上找到一塊Block空間分配。並將該區域從其父節點上取下了。(注意最後一種情況是一個遞歸過程)
源碼:
- static void
- icvGoNextMemBlock( CvMemStorage * storage )
- {
- CV_FUNCNAME( "icvGoNextMemBlock" );
- __BEGIN__;
- if( !storage )
- CV_ERROR( CV_StsNullPtr, "" );
- if( !storage->top || !storage->top->next )
- {
- CvMemBlock *block;
- if( !(storage->parent) )
- {
- CV_CALL( block = (CvMemBlock *)cvAlloc( storage->block_size ));
- }
- else
- {
- CvMemStorage *parent = storage->parent;
- CvMemStoragePos parent_pos;
- cvSaveMemStoragePos( parent, &parent_pos );
- CV_CALL( 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 )
- storage->top = storage->top->next;
- storage->free_space = storage->block_size - sizeof(CvMemBlock);
- assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
- __END__;
- }
(8)cvRestoreMemStoragePos( CvMemStorage * storage, CvMemStoragePos * pos )
該函數將Pos中相應的字段,賦值給Storage相對應的各個字段。注意當Storage是一個新初始化的情況時的特殊處理。
- CV_IMPL void
- cvRestoreMemStoragePos( CvMemStorage * storage, CvMemStoragePos * pos )
- {
- CV_FUNCNAME( "cvRestoreMemStoragePos" );
- __BEGIN__;
- if( !storage || !pos )
- CV_ERROR( CV_StsNullPtr, "" );
- if( pos->free_space > storage->block_size )
- CV_ERROR( CV_StsBadSize, "" );
- /*
- // this breaks icvGoNextMemBlock, so comment it off for now
- if( storage->parent && (!pos->top || pos->top->next) )
- {
- CvMemBlock* save_bottom;
- if( !pos->top )
- save_bottom = 0;
- else
- {
- save_bottom = storage->bottom;
- storage->bottom = pos->top->next;
- pos->top->next = 0;
- storage->bottom->prev = 0;
- }
- icvDestroyMemStorage( storage );
- storage->bottom = save_bottom;
- }*/
- storage->top = pos->top;
- storage->free_space = pos->free_space;
- if( !storage->top )
- {
- storage->top = storage->bottom;
- storage->free_space = storage->top ? storage->block_size - sizeof(CvMemBlock) : 0;
- }
- __END__;
- }