• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            MyMSDN

            MyMSDN記錄開發(fā)新知道

            [C++]內(nèi)存管理(1)

            和大多數(shù)內(nèi)存管理的初衷一致,希望能夠控制內(nèi)存分配和回收,減少內(nèi)存碎片,且通常這樣的內(nèi)存都會預(yù)開一段連續(xù)內(nèi)存空間,然后我們自己來管理這段內(nèi)存。當然通常這樣的需求都很合理,但是實現(xiàn)起來則通常不能完美,比如:效率、算法的選擇、如何減少內(nèi)存碎片、跟蹤管理內(nèi)存分配、性能檢測、對系統(tǒng)內(nèi)存使用的統(tǒng)計、垃圾回收等。下面是我近期實現(xiàn)的一個非常簡陋的程序,甚至可能連基本的要求都無法達到,大家?guī)兔纯矗烤褂卸嗌偃秉c需要被注意和改進,哪些是無法容忍的?

            基本思路是每次分配4M的內(nèi)存空間(可配置),總共10個這樣的內(nèi)存塊,通過鏈表(實際的程序中使用map/multimap來提高效率)來管理內(nèi)存分塊,然后通過修改節(jié)點狀態(tài)來管理內(nèi)存塊。

            投石問路:希望能夠?qū)崿F(xiàn)垃圾回收的機制,最大的問題是如何判斷一個對象已經(jīng)不再被使用了?初步的想法是通過棧地址,找到其上所指的堆地址,對于不在其列的堆地址,將其從堆中移除(標記為待回收)。對以下幾個問題存在疑問:

            1. 對于一個int ** pp = xxx的對象,它的判斷行為是什么?
            2. 對于一個MyClass * pObj = new MyClass; pObj->AnotherObj;,它的判斷行為又是什么?
            3. // ……

            對于垃圾回收以及棧和堆的關(guān)系不是太了解,找到的資料也十分有限,希望有經(jīng)驗的朋友能夠提供幫助。

            詳細設(shè)計:

            內(nèi)存管理

            目的

            方法

            一、固定堆數(shù)量(暫定10份),固定每個堆的內(nèi)存大小(暫定4M),初始堆1個,如果1個堆分配不下,再延伸一個堆,直到分配結(jié)束。可以分配的尺寸不超過單個堆的大小,否則返回NULL,分配失敗。

            二、凌駕于多個堆之上的數(shù)據(jù)結(jié)構(gòu):所有結(jié)構(gòu)可以反查屬于哪個堆。

            a) 內(nèi)存塊尺寸表,一個用于描述所有堆能夠存放的內(nèi)存塊(chunk)尺寸,尺寸按順序排列。

            每個節(jié)點應(yīng)該包含以下信息:

            i. 空閑區(qū)塊的尺寸;

            ii. 空閑區(qū)塊所屬的堆;

            為了優(yōu)化查詢搜索,這里將相同尺寸歸并,并列出對應(yīng)堆和每個堆上該尺寸的區(qū)塊的大小:

            multimap<Key : Size, Value : struct(heap, count) >

            b) 一個用于存放堆信息的數(shù)組,數(shù)組的大小為固定堆數(shù)量。

            每個節(jié)點應(yīng)該包含以下信息:

            i. 堆的句柄;

            1. 連續(xù)內(nèi)存空間的一塊堆內(nèi)存,用來存儲數(shù)據(jù)值。

            ii. 堆的最大可用區(qū)塊空間;

            iii. 堆的最小可用區(qū)塊空間;

            iv. 用于管理堆的內(nèi)部區(qū)域鏈表:

            1. 一個完整堆內(nèi)區(qū)塊鏈表,按照地址升序存放。

            鏈表的每個節(jié)點,代表每一個獨立的內(nèi)存區(qū)塊,區(qū)塊是用戶申請的最小粒度。每個節(jié)點應(yīng)該包含以下信息:

            a) 區(qū)塊的尺寸;

            b) 區(qū)塊的狀態(tài)(未格式化,空閑,占用);

            c) 區(qū)塊的首地址指針;

            為了優(yōu)化查詢搜索,這里也可用map:

            Map<Key : Offset, Value : struct (size, status, hHeap, pointer)>

            三、內(nèi)部計數(shù)器,用于診斷和性能分析,碎片分析

            a) 分配次數(shù)計數(shù)器

            b) 分配成功次數(shù)計數(shù)器

            四、如何快速查找可分配區(qū)塊,并分配內(nèi)存?

            輸入:預(yù)分配區(qū)塊尺寸

            輸出:指向預(yù)分配區(qū)塊的指針

            1、 如果預(yù)分配尺寸大于單塊固定堆尺寸,返回NULL;

            2、 查詢內(nèi)存塊尺寸表,查找最合適的(尺寸>=預(yù)分配尺寸的最接近內(nèi)存塊,如果是大于的情況)內(nèi)存塊,返回其所屬的堆句柄;

            3、 找到對應(yīng)堆的內(nèi)部區(qū)域鏈表,順序查找最合適的內(nèi)存塊(條件和前述相同);作為調(diào)試信息的一部分,判斷,如果查找不到該內(nèi)存塊,則完全同步一次堆剩余尺寸到區(qū)域尺寸映射表(如果該方案的失敗率過高,則應(yīng)該廢除該方法)

            4、 針對找到的內(nèi)存塊執(zhí)行后續(xù)操作(包括:插入鏈表、修改原始節(jié)點尺寸/狀態(tài)、將內(nèi)存塊首地址和對應(yīng)堆更新到映射表中,更新內(nèi)存塊尺寸表(根據(jù)找到的區(qū)塊的尺寸和區(qū)塊所屬堆來找,將其更新或移除)等);

            5、 返回對應(yīng)指針。

            五、釋放內(nèi)存塊

            輸入:void*內(nèi)存塊指針

            輸出:BOOL

            1、 查表確定該內(nèi)存塊屬于哪個堆?返回堆句柄;

            2、 查找該堆對應(yīng)的完整列表,找到該堆的節(jié)點,修改該節(jié)點的狀態(tài)為Free;

            3、 合并相鄰項,[該步驟的執(zhí)行導(dǎo)致該鏈表中不存在兩塊連續(xù)的Free區(qū)塊]。

            a) 前項檢測:

            前一項如果為Free,將前項size+=當前項size,刪除當前項。

            b) 后項檢測:(如果前項檢測無結(jié)果)

            如果后項為Free,將當前項size=size+后項size,刪除后項。

            4、 更新內(nèi)存尺寸表。

            5、 更新內(nèi)存堆映射表。

            源碼:

            memory_manager_def.h

            /*
            說明:定義與內(nèi)存管理相關(guān)的常量
            */
            
            #pragma once
            
            #include "stdafx.h"
            #include <map>
            
            /*堆的最大數(shù)量*/
            const size_t MAX_HEAP_COUNT = 10;
            
            /*每一塊堆的尺寸*/
            const size_t HEAP_SIZE ((size_t)( 4 * (1024 /** 1024*/)/*MB*/)); // (M)
            
            const unsigned long FRAGMENT_SIZE = 8; // 當小于byte的時候,被定義為碎片
            
            /*同一塊內(nèi)存區(qū)域之間,兩個指針之間的偏移量*/
            typedef unsigned long offset_type;
            typedef unsigned char* byte_ptr_type;
            
            typedef enum _CHUNK_STATUS{ 
                Unformated,
                Free,
                Occupied
            } CHUNK_STATUS;
            
            

            memory_manager.h

            /*
            說明:定義內(nèi)存管理接口
            */
            
            #pragma once
            #include "stdafx.h"
            #include "memory_manager_def.h"
            #include "trace.h"
            #include <map>
            
            typedef struct _free_chunk 
            {
                _free_chunk():hHeap(0), count(0){}
                _free_chunk(HANDLE _hHeap, size_t _count):hHeap(_hHeap), count(_count){}
                // _free_chunk(const _free_chunk& rChunk);
            
                /*-----members-----*/
                HANDLE hHeap;
                size_t count;
            } free_chunk;
            
            /*內(nèi)存尺寸表*/
            typedef std::multimap<size_t, free_chunk> free_chunk_table_type;
            typedef std::pair<free_chunk_table_type::iterator, free_chunk_table_type::iterator> free_chunk_range_type;
            
            typedef std::map<void*, HANDLE> chunk_heap_table_type;
            
            /*chunk:是指一個內(nèi)存固定區(qū)塊內(nèi)的一個可分配內(nèi)存區(qū)塊*/
            typedef struct _chunk_type
            {
                _chunk_type():size(0), status(Free), hHeap(0), pHead(0){}
                size_t size;
                /*當前區(qū)塊的狀態(tài)*/
                CHUNK_STATUS status;
                /*當前區(qū)塊所屬的堆*/
                HANDLE hHeap;
                /*當前區(qū)塊的首地址*/
                void* pHead;
            } chunk_type;
            
            typedef std::map<offset_type, chunk_type> block_table_type;
            typedef enum _CHUNK_INDEX_TYPE
            {
                BeyondFirst,
                Normal,
                BeyondLast,
                Undefined
            } CHUNK_INDEX_TYPE;
            
            /*block:是指一個內(nèi)存固定區(qū)塊*/
            typedef struct _block_type
            {
                _block_type():hHeap(0)
                    //, max_free_chunk_size(0),min_free_chunk_size(0)
                {}
                HANDLE hHeap;
                ///*當前內(nèi)存塊中剩余的最大塊尺寸(狀態(tài)為Free)*/
                //size_t max_free_chunk_size;
                ///*當前內(nèi)存塊中剩余的最小塊尺寸*/
                //size_t min_free_chunk_size;
                size_t size;
                block_table_type full_list;
                /*當前堆的首地址*/
                void* pHead;
            } block_type;
            
            class memory_manager
            {
            public:
                memory_manager();
                virtual ~memory_manager();
            
                void *allocate(size_t size);
                void deallocate(void * ptr);
            
                void debug_snapshot(void);
            private:
                void heap_list_init(void);
                void heap_list_i_init(size_t i);
                BOOL heap_create_new_one(void);
            
                inline HANDLE heap_create_base(void);
                inline BOOL heap_destroy_base(HANDLE hHeap);
                inline void* heap_alloc_base(HANDLE hHeap, size_t size=HEAP_SIZE);
                inline BOOL heap_dealloc_base(HANDLE hHeap, LPVOID lpMem);
            
                void heap_query_information(HANDLE hHeap);
                size_t heap_index(HANDLE hHeap);
            
                CHUNK_INDEX_TYPE prev_chunk(block_table_type &list, int offset, OUT chunk_type * pChunk);
                CHUNK_INDEX_TYPE next_chunk(block_table_type &list, int offset, OUT chunk_type * pChunk);
                void remove_chunk(block_table_type &list, int heapIndex, int offset);
            
                void free_chunk_list_add(size_t size, HANDLE hHeap);
                void free_chunk_list_remove(size_t size, HANDLE hHeap);
                BOOL get_available_chunk(IN size_t size, OUT free_chunk* pChunk);
            
                HANDLE which_heap(void * ptr);
                void set_chunk_heap(void * ptr, HANDLE hHeap);
                void remove_chunk_heap(void *ptr);
            private:
                block_type heap_list[MAX_HEAP_COUNT];
                /*當從程序里返回內(nèi)存塊的時候,記錄內(nèi)存塊與堆的對應(yīng)關(guān)系,當釋放的時候,取出對應(yīng)的堆*/
                chunk_heap_table_type chunk_heap_table;
                /*一個用于描述所有堆能夠存放的內(nèi)存塊(chunk)尺寸,尺寸按順序排列。*/
                free_chunk_table_type free_chunk_table;
            };
            

            trace.h

            #ifndef _GC_TRACE_H
            #define _GC_TRACE_H
            
            #ifdef _DEBUG
            
            //#define OUTPUT_TO_CONSOLE
            
            void _Trace(LPCWSTR lpszFmt, ...);
            void _Trace(LPCSTR lpszFmt, ...);
            
            #define _TRACE _Trace
            #define _W(x) (LPCWSTR)_T(x)
            #else  
            #define _TRACE  
            #define _W(x) x
            #endif 
            
            #endif

            memory_manager.cpp

            /*
            說明:定義內(nèi)存管理的實現(xiàn)部分
            */
            #include "stdafx.h"
            #include "memory_manager.h"
            
            memory_manager::memory_manager()
            {
                heap_list_init();
            }
            
            memory_manager::~memory_manager()
            {
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    if(heap_list[i].hHeap != 0)
                    {
                        heap_list[i].size = 0;
                        heap_dealloc_base(heap_list[i].hHeap, heap_list[i].pHead);
                        heap_destroy_base(heap_list[i].hHeap);
                    }
                }
            }
            
            void *memory_manager::allocate(size_t size)
            {
                // 1、    如果預(yù)分配尺寸大于單塊固定堆尺寸,返回NULL;
                if( size > HEAP_SIZE)
                {
                    _TRACE(_W("申請內(nèi)存尺寸%d > 單區(qū)內(nèi)存最大尺寸%d.\n"), size, HEAP_SIZE);
                    return 0;
                }
                else if(size == 0)
                {
                    _TRACE(_W("申請內(nèi)存尺寸為%d.\n"), size);
                    return 0;
                }
            
                // 2、    查詢內(nèi)存塊尺寸表,查找最合適的(尺寸>=預(yù)分配尺寸的最接近內(nèi)存塊,如果是大于的情況)內(nèi)存塊,返回其所屬的堆句柄;
                free_chunk freeChunk;
                if( !get_available_chunk(size, &freeChunk) )
                {
                    for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                    {
                        if(heap_list[i].hHeap == 0)
                        {
                            heap_list_i_init(i);
                            return allocate(size);
                        }
                    }
                    return 0;
                }
            
                void* mem;
                HANDLE hHeap;
                size_t removeSize;
            
                // 3、    找到對應(yīng)堆的內(nèi)部區(qū)域鏈表,順序查找最合適的內(nèi)存塊(條件和前述相同);作為調(diào)試信息的一部分,判斷,如果查找不到內(nèi)存塊該內(nèi)存塊,則完全同步一次堆剩余尺寸到區(qū)域尺寸映射表(如果該方案的失敗率過高,則應(yīng)該廢除該方法)
                int index = heap_index(freeChunk.hHeap);
                if(index == -1)
                {
            #ifdef _DEBUG
                    _TRACE(_W("找不到該堆信息。\n"));
            #endif
                }
                block_table_type *full_list_ptr = &heap_list[index].full_list;
                for (block_table_type::iterator it = full_list_ptr->begin();
                    it != full_list_ptr->end(); ++it)
                {
                    if(it->second.status == Free && it->second.size >= size)
                    {
                        if(it->second.size == size)
                        {
                            // 4、    針對找到的內(nèi)存塊執(zhí)行后續(xù)操作(包括:插入鏈表、修改原始節(jié)點尺寸/狀態(tài)、將內(nèi)存塊首地址和對應(yīng)堆更新到映射表中,更新內(nèi)存塊尺寸表(根據(jù)找到的區(qū)塊的尺寸和區(qū)塊所屬堆來找,將其更新或移除)等);
                           
                            it->second.status = Occupied;
                            mem = it->second.pHead;
                            hHeap = it->second.hHeap;
                            removeSize = it->second.size;
            
                            // 從內(nèi)存塊尺寸表中,移除該塊內(nèi)存
                            free_chunk_list_remove(removeSize, hHeap);
                        }
                        else /*if(it->second.size > size)*/
                        {
                            // 4、    針對找到的內(nèi)存塊執(zhí)行后續(xù)操作(包括:插入鏈表、修改原始節(jié)點尺寸/狀態(tài)、將內(nèi)存塊首地址和對應(yīng)堆更新到映射表中,更新內(nèi)存塊尺寸表(根據(jù)找到的區(qū)塊的尺寸和區(qū)塊所屬堆來找,將其更新或移除)等);
                            int restSize = it->second.size - size;
                            int originalSize = it->second.size;
                            int firstChunkOffset = static_cast<byte_ptr_type>(it->second.pHead) - static_cast<byte_ptr_type>(heap_list[index].pHead);
                            int secondChunkOffset = static_cast<byte_ptr_type>(it->second.pHead) - static_cast<byte_ptr_type>(heap_list[index].pHead) + restSize;
            #ifdef _DEBUG
                            _TRACE(_W("此塊內(nèi)存塊大小為%d、即將分配%d、分配完后將剩%d、左側(cè)空閑塊偏移%d、右側(cè)即將分配的塊偏移%d.\n"), originalSize, size, restSize, firstChunkOffset, secondChunkOffset);
            #endif
                            mem = static_cast<void*>(static_cast<byte_ptr_type>(heap_list[index].pHead) + secondChunkOffset);
                            hHeap = it->second.hHeap;
            
                            chunk_type firstChunk, secondChunk;
            
                            firstChunk.size = restSize;
                            firstChunk.status = Free;
                            firstChunk.hHeap = heap_list[index].hHeap;
                            firstChunk.pHead = it->second.pHead;
            
                            secondChunk.size = size;
                            secondChunk.status = Occupied;
                            secondChunk.hHeap = heap_list[index].hHeap;
                            secondChunk.pHead = static_cast<byte_ptr_type>(it->second.pHead) + restSize;
            
                            full_list_ptr->erase(it);
                            (*full_list_ptr)[firstChunkOffset] = firstChunk;
                            (*full_list_ptr)[secondChunkOffset] = secondChunk;
            
                            // 從內(nèi)存塊尺寸表中,
                            // 1、移除原始尺寸模塊;
                            // 2、增加新的可用內(nèi)存塊;
                            free_chunk_list_remove(originalSize, hHeap);
                            free_chunk_list_add(restSize, hHeap);
                        }
                        break;
                    }
                }
            
                // 將當前選中的內(nèi)存塊存進映射表中
                set_chunk_heap(mem, hHeap);
            
                // 5、    返回對應(yīng)指針。
                return mem;
            }
            
            void memory_manager::deallocate(void * ptr)
            {
                // 1、    查表確定該內(nèi)存塊屬于哪個堆?返回堆句柄;
                HANDLE hHeap = which_heap(ptr);
                size_t deallocateSize;
                if(hHeap == 0)
                {
            #ifdef _DEBUG
                    _TRACE(_W("所訪問指針不在可管理的堆中.\n"));
            #endif
                }
                else
                {
                    // 2、    查找該堆對應(yīng)的完整列表,找到該堆的節(jié)點,修改該節(jié)點的狀態(tài)為Free;
                    int index = heap_index(hHeap);
                    int offset = static_cast<byte_ptr_type>(ptr) - static_cast<byte_ptr_type>(heap_list[index].pHead);
            
                    deallocateSize = heap_list[index].full_list[offset].size;
            #ifdef _DEBUG
                    _TRACE(_W("刪除的內(nèi)存塊偏移為%d.\n"), offset);
            
                    if( heap_list[index].full_list[offset].hHeap == 0)
                    {
                        _TRACE(_W("所訪問的指針在可管理堆中無記錄.\n"));
                        return;
                    }
                    if(heap_list[index].full_list[offset].status != Occupied)
                    {
                        _TRACE(_W("所訪問的指針狀態(tài)不是已占用,原則上應(yīng)該是已占用.\n"));
                    }
            #endif
                    heap_list[index].full_list[offset].status = Free;
                    
                    // 3、    合并相鄰項,[該步驟的執(zhí)行導(dǎo)致該鏈表中不存在兩塊連續(xù)的Free區(qū)塊]。
                    remove_chunk(heap_list[index].full_list, index, offset);
            
                    // 4、    更新內(nèi)存尺寸表。
                    // 已經(jīng)包含在remove_chunk中
            
                    // 5、 更新內(nèi)存堆映射表。
                    remove_chunk_heap(ptr);
                }
            }
            
            /*輸出某一瞬間的各列表信息
            */
            void memory_manager::debug_snapshot(void)
            {
            #ifdef _DEBUG
                _TRACE(_W("-----------start snapshot-------------\n"));
                _TRACE(_W("內(nèi)存塊尺寸表:\n"));
                free_chunk_table_type::const_iterator cIter = free_chunk_table.begin();
            
                int fragmentCounter = 0;
                int totalFreeCounter = 0;
                for(; cIter != free_chunk_table.end(); ++cIter)
                {
                    _TRACE(_W("    在Heap=%8x上有Size=%d的塊%d個.\n"), cIter->second.hHeap, cIter->first, cIter->second.count);
                    ++totalFreeCounter;
                    if(cIter->first <= FRAGMENT_SIZE)
                        fragmentCounter+=cIter->second.count;
                }
                _TRACE(_W("    從“內(nèi)存塊尺寸表”來看,總共有%d塊空閑內(nèi)存,其中碎片(<= %d byte)的內(nèi)存塊有%d個.\n"), totalFreeCounter, FRAGMENT_SIZE, fragmentCounter);
            
                int heapListItemCounter[MAX_HEAP_COUNT] = {};
                int heapListItemTotalCounter = 0;
                int heapListItemFreeCounter[MAX_HEAP_COUNT] = {};
                int heapListItemTotalFreeCounter = 0;
                int heapListItemOccupidCounter[MAX_HEAP_COUNT] = {};
                int heapListItemTotalOccupidCounter = 0;
                int heapListItemFragmentCounter[MAX_HEAP_COUNT] = {};
                int heapListItemTotalFragmentCounter = 0;
            
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    if(heap_list[i].hHeap != 0)
                    {
                        block_table_type * full_list_ptr = &heap_list[i].full_list;
                        block_table_type::const_iterator cIterList = full_list_ptr->begin();
                        for(; cIterList != full_list_ptr->end(); ++cIterList)
                        {
                            ++heapListItemCounter[i];
                            if(cIterList->second.status == Free)
                                ++heapListItemFreeCounter[i];
                            else if(cIterList->second.status == Occupied)
                                ++heapListItemOccupidCounter[i];
                            // 碎片數(shù)量
                            if(cIterList->second.size <= FRAGMENT_SIZE && cIterList->second.status == Free)
                                ++heapListItemFragmentCounter[i];
                        }
                    }
                }
                _TRACE(_W("完全鏈表:\n"));
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    if(heapListItemFreeCounter[i] + heapListItemOccupidCounter[i] != heapListItemCounter[i])
                        _TRACE(_W("    ----------內(nèi)存完全列表可能存在問題!\n"));
                    _TRACE(_W("    第%d塊堆擁有%d空閑內(nèi)存、%d已占內(nèi)存、%d碎片\n"), i, heapListItemFreeCounter[i], heapListItemOccupidCounter[i], heapListItemFragmentCounter[i]);
            
                    heapListItemTotalFreeCounter += heapListItemFreeCounter[i];
                    heapListItemTotalOccupidCounter +=heapListItemOccupidCounter[i];
                    heapListItemTotalFragmentCounter +=heapListItemFragmentCounter[i];
                    heapListItemTotalCounter += heapListItemCounter[i];
                }
                _TRACE(_W("所有堆中共有%d內(nèi)存塊、%d空閑內(nèi)存、%d已占內(nèi)存、%d碎片\n"), 
                    heapListItemTotalCounter,
                    heapListItemTotalFreeCounter,  
                    heapListItemTotalOccupidCounter,
                    heapListItemTotalFragmentCounter);
            
                _TRACE(_W("------------end  snapshot-------------\n"));
            #endif
            }
            
            /*堆初始化(全部)
            策略:
                1、設(shè)置堆列表中的堆句柄為、最大可用尺寸為、最小可用尺寸為、可分配內(nèi)存首地址為
                */
            void memory_manager::heap_list_init(void)
            {
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    heap_list[i].hHeap = 0;
                    heap_list[i].pHead = 0;
                }
            }
            
            /*堆初始化(單個)
            策略:
                1、初始化堆各個字段,并對堆實行完全內(nèi)存分配。其中堆尺寸、最大最小可用尺寸均為完全分配尺寸
            */
            void memory_manager::heap_list_i_init(size_t index)
            {
                heap_list[index].hHeap = heap_create_base();
                heap_list[index].size = HEAP_SIZE;
                heap_list[index].pHead = heap_alloc_base(heap_list[index].hHeap, heap_list[index].size);
            
                free_chunk_list_add(HEAP_SIZE, heap_list[index].hHeap);
            
                chunk_type freeChunk;
                freeChunk.hHeap = heap_list[index].hHeap;
                freeChunk.pHead = heap_list[index].pHead;
                freeChunk.size = heap_list[index].size;
                freeChunk.status = Free;
                heap_list[index].full_list[0] = freeChunk;
            }
            
            BOOL memory_manager::heap_create_new_one(void)
            {
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    if(heap_list[i].hHeap == 0)
                    {
                        heap_list_i_init(i);
                        return TRUE;     
                    }
                    return FALSE;
                }
                return FALSE;
            }
            
            #pragma region heap func
            /*創(chuàng)建堆對象
            策略:
                1、創(chuàng)建一個固定大小的堆
                2、啟用LFH以減小內(nèi)存碎片(如果允許的話)
            */
            inline HANDLE memory_manager::heap_create_base(void)
            {
                /*The HeapCreate function rounds dwMaximumSize up to the next page boundary, and then reserves a block of that size in the process's virtual address space for the heap. If allocation requests made by the HeapAlloc or HeapReAlloc functions exceed the size specified by dwInitialSize, the system commits additional pages of memory for the heap, up to the heap's maximum size. If dwMaximumSize is not zero, the heap size is fixed and cannot grow. The largest memory block that can be allocated from the heap is slightly less than 0x7FFF8 bytes. Requests to allocate larger blocks fail, even if the maximum size of the heap is large enough to contain the block. */
                HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, HEAP_SIZE, 0/*growable*/);
                // 啟用LFH(ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/memory/base/low_fragmentation_heap.htm)
                // 以減少內(nèi)存碎片
            #ifdef _DEBUG
                heap_query_information(hHeap);
            #endif
                ULONG  HeapFragValue = 2L;
                // 如果啟用LFH不成功
                if(!HeapSetInformation(hHeap, HeapEnableTerminationOnCorruption, &HeapFragValue, sizeof(HeapFragValue)))
                {
                    _TRACE(_W("LFH is unabled. Error code is %d\n"), GetLastError());
                }
            #ifdef _DEBUG
                heap_query_information(hHeap);
            #endif
                return hHeap;
            }
            
            /*釋放堆對象*/
            inline BOOL memory_manager::heap_destroy_base(HANDLE hHeap)
            {
                return HeapDestroy(hHeap);
            }
            /*申請內(nèi)存塊
            策略:
            */
            inline void* memory_manager::heap_alloc_base(HANDLE hHeap, size_t size)
            {
                void* mem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, size);
            #ifdef _DEBUG
                if(NULL == mem)
                {
                    _TRACE(_W("HeapAlloc error. Error code is %d\n"), GetLastError());
                }
            #endif
                return mem;
            }
            
            /*釋放內(nèi)存塊
            參數(shù):
                hHeap:堆句柄
                lpMem:首地址
            */
            inline BOOL memory_manager::heap_dealloc_base(HANDLE hHeap, LPVOID lpMem)
            {
                return HeapFree(hHeap, 0, lpMem);
            }
            
            /*查找某個堆屬于堆列表中的第幾個
            */
            size_t memory_manager::heap_index(HANDLE hHeap)
            {
                for(size_t i = 0; i < MAX_HEAP_COUNT; ++i)
                {
                    if( heap_list[i].hHeap == hHeap )
                        return i;
                }
                return -1;
            }
            
            CHUNK_INDEX_TYPE memory_manager::prev_chunk(block_table_type &list, int offset, OUT chunk_type * pChunk)
            {
                if(pChunk == 0)
                    return Undefined;
                if(list[offset].hHeap == 0)
                    return Undefined;
                block_table_type::iterator it = list.find(offset);
                if(it == list.begin())
                    return BeyondFirst;
                if(it == list.end())
                    return Undefined;
            
                block_table_type::iterator itPrev = --it;
                ++it;
            
                pChunk->hHeap = (itPrev)->second.hHeap;
                pChunk->pHead = (itPrev)->second.pHead;
                pChunk->size = (itPrev)->second.size;
                pChunk->status = (itPrev)->second.status;
            
                return Normal;
            }
            
            CHUNK_INDEX_TYPE memory_manager::next_chunk(block_table_type &list, int offset, OUT chunk_type * pChunk)
            {
                if(pChunk == 0)
                    return Undefined;
                if(list[offset].hHeap == 0)
                    return Undefined;
                block_table_type::iterator it = list.find(offset);
                if(it == list.end())
                    return Undefined;
            
                block_table_type::iterator itNext = ++it;
                --it;
            
                if(itNext == list.end())
                    return BeyondLast;
            
                pChunk->hHeap = (itNext)->second.hHeap;
                pChunk->pHead = (itNext)->second.pHead;
                pChunk->size = (itNext)->second.size;
                pChunk->status = (itNext)->second.status;
            
                return Normal;
            }
            void memory_manager::remove_chunk(block_table_type &list, int heapIndex, int offset)
            {
                // a)    前項檢測:
                // 前一項如果為Free,將前項size+=當前項size,刪除當前項。
                chunk_type prevFreeChunk;
                if( prev_chunk(heap_list[heapIndex].full_list, offset, &prevFreeChunk) != BeyondFirst)
                {
                    if(prevFreeChunk.status == Free)
                    {
                        int prevOffset = static_cast<byte_ptr_type>(prevFreeChunk.pHead) - static_cast<byte_ptr_type>(heap_list[heapIndex].pHead);
                        free_chunk_list_remove(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
                        heap_list[heapIndex].full_list[prevOffset].size += heap_list[heapIndex].full_list[offset].size;
                        free_chunk_list_add(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
                        heap_list[heapIndex].full_list.erase(offset);
            #ifdef _DEBUG
                        _TRACE(_W("執(zhí)行前項檢測且前項狀態(tài)為空閑,可執(zhí)行合并。前項偏移為%d\n"), prevOffset);
            #endif
                        return;
                    }
                }
            
                chunk_type nextFreeChunk;
                // b)    后項檢測:(如果前項檢測無結(jié)果)
                // 如果后項為Free,將當前項size=size+后項size,刪除后項。
                if( next_chunk(heap_list[heapIndex].full_list, offset, &nextFreeChunk) != BeyondLast)
                {
                    if(nextFreeChunk.status == Free)
                    {
                        int nextOffset = static_cast<byte_ptr_type>(nextFreeChunk.pHead) - static_cast<byte_ptr_type>(heap_list[heapIndex].pHead);
                        free_chunk_list_remove(heap_list[heapIndex].full_list[nextOffset].size, heap_list[heapIndex].hHeap);
                        heap_list[heapIndex].full_list[offset].size += heap_list[heapIndex].full_list[nextOffset].size;
                        free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
                        heap_list[heapIndex].full_list.erase(nextOffset);
            #ifdef _DEBUG
                        _TRACE(_W("執(zhí)行后項檢測且后項狀態(tài)為空閑,可執(zhí)行合并。后項偏移為%d\n"), nextOffset);
            #endif
                        return;
                    }
                }
                free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            
            /*
            查詢堆信息,輔助調(diào)試,可以查看當前堆的特性
            */
            void memory_manager::heap_query_information(HANDLE hHeap)
            {
                ULONG heapInfo;
                SIZE_T returnLength;
                if(!HeapQueryInformation(hHeap, HeapCompatibilityInformation, &heapInfo, sizeof(ULONG), &returnLength))
                {
                    _TRACE(_W("HeapInformation:%d, returnLength:%d.Error code is %d\n"), heapInfo, returnLength, GetLastError());
                }
                else
                {
                    _TRACE(_W("HeapInformation:%d, returnLength:%d.\n"), heapInfo, returnLength);
                }
            }
            
            #pragma endregion
            
            /*向內(nèi)存尺寸表中添加尺寸信息
            test:
            free_chunk_list_add(50, (HANDLE)0);
            free_chunk_list_add(50, (HANDLE)0);
            free_chunk_list_add(10, (HANDLE)1);
            free_chunk_list_add(20, (HANDLE)3);
            free_chunk_list_add(20, (HANDLE)0);
            free_chunk_list_add(10, (HANDLE)1);
            free_chunk_list_add(70, (HANDLE)3);
            free_chunk_list_add(50, (HANDLE)2);
            */
            void memory_manager::free_chunk_list_add(size_t size, HANDLE hHeap)
            {
                free_chunk_range_type range = free_chunk_table.equal_range(size);
                // if not found.
                if(range.first == range.second)
                {
                    free_chunk freeChunk;
                    freeChunk.count = 1;
                    freeChunk.hHeap = hHeap;
            
                    free_chunk_table.insert(std::make_pair(size, freeChunk)); // copy 
                    return;
                }
                
                // if found.
                for(free_chunk_table_type::iterator i = range.first; i != range.second; ++i)
                {
                    if(i->second.hHeap == hHeap)
                    {
                        i->second.count = i->second.count + 1;
                        return;
                    }
                }
            
                // 否則如果沒有找到該堆所對應(yīng)的相同尺寸的信息
                free_chunk freeChunk;
                freeChunk.count = 1;
                freeChunk.hHeap = hHeap;
            
                free_chunk_table.insert(std::make_pair(size, freeChunk)); // copy 
            }
            
            /*從內(nèi)存尺寸表中移除尺寸信息
            test:
            free_chunk_list_remove(50, (HANDLE)0);
            free_chunk_list_remove(50, (HANDLE)0);
            free_chunk_list_remove(10, (HANDLE)1);
            free_chunk_list_remove(20, (HANDLE)3);
            free_chunk_list_remove(20, (HANDLE)0);
            free_chunk_list_remove(10, (HANDLE)1);
            free_chunk_list_remove(70, (HANDLE)3);
            free_chunk_list_remove(50, (HANDLE)2);
            */
            void memory_manager::free_chunk_list_remove(size_t size, HANDLE hHeap)
            {
                free_chunk_range_type range = free_chunk_table.equal_range(size);
                // if not found.
                if(range.first == range.second)
                {
            #ifdef _DEBUG
                    _TRACE(_W("從內(nèi)存尺寸表中查找size=%d的內(nèi)存時候,無法找到記錄.\n"), size);
            #endif // _DEBUG
                }
            
                // if found.
                for(free_chunk_table_type::iterator i = range.first; i != range.second; ++i)
                {
                    if(i->second.hHeap == hHeap)
                    {
                        i->second.count = i->second.count - 1;
                        if(i->second.count == 0)
                        {
                            free_chunk_table.erase(i);
                        }
                        return;
                    }
                }
            
            #ifdef _DEBUG
                _TRACE(_W("從內(nèi)存尺寸表中查找size=%d的內(nèi)存時候,無法找到記錄.\n"), size);
            #endif // _DEBUG
            }
            
            /*通過可用鏈表查詢可用的內(nèi)存區(qū)塊
            策略:
                1、遍歷可用區(qū)塊鏈表(該鏈表已經(jīng)按尺寸從小到大順序排列)
                2、尋找可用
            */
            BOOL memory_manager::get_available_chunk(IN size_t size, OUT free_chunk* pChunk)
            {
                free_chunk_table_type::iterator fct_iter;
                for(fct_iter = free_chunk_table.begin();
                    fct_iter != free_chunk_table.end(); ++fct_iter)
                {
                    size_t available_size = (*fct_iter).first;
                    if(available_size >= size)
                    {
                        *pChunk = (*fct_iter).second;
                        return TRUE;
                    }
                    else
                    {
            #ifdef _DEBUG
                    _TRACE(_W("找不到合適大小的內(nèi)存塊.\n"));
            #endif
                    }
                }
            
                return FALSE;
            }
            
            /*某個任意指針屬于哪個堆,返回值為表示不是在堆列表中的堆
            策略:
            1、本設(shè)計中存在返回指針以及所屬指針的字典映射
            2、通過查表法找出當前指針所屬的堆信息
            */
            HANDLE memory_manager::which_heap(void * ptr)
            {
                HANDLE hHeap = chunk_heap_table[ptr];
                if( NULL == hHeap )
                {
                    _TRACE(_W("該指針不屬于任意內(nèi)存塊.\n"));
                    return 0;
                }
                else
                {
            #ifdef _DEBUG
                    _TRACE(_W("當前使用的指針來自第%d塊堆.\n"), heap_index(hHeap));
            #endif
                    return hHeap;
                }
            }
            
            /*將指針和對應(yīng)堆信息存進字典備查
            策略:
            1、本設(shè)計中存在返回指針以及所屬指針的字典映射
            2、以指針作為鍵值,將對應(yīng)堆句柄作為值
            */
            void memory_manager::set_chunk_heap(void * ptr, HANDLE hHeap)
            {
            #ifdef _DEBUG
                if(chunk_heap_table[ptr] != 0)
                {
                    _TRACE(_W("在此之前已經(jīng)有相同的指針存在于表中,還未釋放.\n"));
                    return;
                }
            #endif  
                chunk_heap_table[ptr] = hHeap;
            }
            
            /*將指針和對應(yīng)堆信息移出字典
            策略:
            1、本設(shè)計中存在返回指針以及所屬指針的字典映射
            2、當該指針作廢后,此處移走對應(yīng)項
            */
            void memory_manager::remove_chunk_heap(void *ptr)
            {
            #ifdef _DEBUG
                HANDLE hHeap = which_heap(ptr);
            #endif
                chunk_heap_table.erase(ptr);
            #ifdef _DEBUG
                _TRACE(_W("指針%p已經(jīng)從第%d塊堆中移除.\n"), ptr, heap_index( hHeap ));
            #endif  
            }

            memory_manager_main.cpp

            // memory_manager.cpp : 定義控制臺應(yīng)用程序的入口點。
            //
            
            #include "stdafx.h"
            #include "memory_manager.h"
            #include <iostream>
            #include <vector>
            
            void run(void)
            {
                memory_manager mm;
                std::vector<void *> pointers;
                int totalMemory = 0;
                int max = 0;
            
                int curr = 0;
                for(int i = 1; i < HEAP_SIZE  * 11; i+=(sizeof(int)))
                {
                    _TRACE(_W("開始申請%d大小的內(nèi)存\n"), i);
                    void * mem = mm.allocate(sizeof(int));
            
                    if(mem != 0)
                        pointers.push_back(mem);
                    else
                        break;
            
                    int *p = (int *)mem;
                    *p = i;
            
                    mm.debug_snapshot();
                    totalMemory += i;
                    if(max < i)
                        max = i;
            
                    _TRACE(_W("--------%d---------\n"), ++curr);
                }
            
                _TRACE(_W("累計申請內(nèi)存數(shù)量%d、申請%d次、申請的最大內(nèi)存為%d。\n"), totalMemory, curr, max);
            
                mm.debug_snapshot();
                _TRACE(_W("====================開始釋放內(nèi)存。\n"));
                std::vector<void *>::const_iterator cIter = pointers.begin();
                for(; cIter != pointers.end(); ++cIter)
                {
                    int *p = static_cast<int *>(*cIter);
                    std::cout << *p << " ";
                    mm.deallocate(*cIter);
                    mm.debug_snapshot();
                    _TRACE(_W("--------%d---------\n"), --curr);
                }
            }
            int _tmain(int argc, _TCHAR* argv[])
            {
                run();
            
                getchar();
                return 0;
            }
            
            

            trace.cpp

            #include "stdafx.h"
            #include "trace.h"
            
            void _Trace(LPCWSTR lpszFmt, ...)  
            {  
                va_list args;  
                va_start(args, lpszFmt);  
                int len = _vscwprintf(lpszFmt, args) + 1;  
                wchar_t* lpszBuf = new wchar_t[len];  
                vswprintf_s(lpszBuf, len, lpszFmt, args);  
                va_end(args);  
                OutputDebugStringW(lpszBuf);  
            #ifdef OUTPUT_TO_CONSOLE
                wprintf(lpszBuf);
            #endif
                delete[] lpszBuf;  
            }  
            void _Trace(LPCSTR lpszFmt, ...)  
            {  
                va_list args;  
                va_start(args, lpszFmt);  
                int len = _vscprintf(lpszFmt, args) + 1;  
                char* lpszBuf = new char[len];  
                vsprintf_s(lpszBuf, len, lpszFmt, args);  
                va_end(args);  
                OutputDebugStringA(lpszBuf);
            #ifdef OUTPUT_TO_CONSOLE
                printf(lpszBuf);
            #endif
                delete[] lpszBuf;  
            }

            posted on 2010-07-06 22:45 volnet 閱讀(3846) 評論(17)  編輯 收藏 引用 所屬分類: C/C++

            評論

            # re: [C++]內(nèi)存管理(1) 2010-07-06 23:29 OwnWaterloo

            請教一下: 這個排版是怎么做的? live writter?  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-06 23:34 volnet

            @OwnWaterloo
            嗯,樣式上,我自己有定義了幾個簡單的樣式。windows live writer+vspaste插件用來貼代碼。黃色部分的詳細設(shè)計,是我之前在Word寫好的,直接貼過來,可能樣式略有變化。
              回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-06 23:34 volnet

            源代碼下載:
            http://m.shnenglu.com/Files/mymsdn/memory_manager.rar  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 00:08 OwnWaterloo

            @volnet
            詳細設(shè)計部分在cppblog上調(diào)整過樣式吧?
            我見過一個白色的頁面, 過段時間刷新后, 就變黃色了。
            很用心~
              回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 08:58 volnet

            @OwnWaterloo
            希望您多指教啊  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 09:48 pcm

            既然“通過棧地址,找到其上所指的堆地址,對于不在其列的堆地址,將其從堆中移除”,那么就沒必要自己管理內(nèi)存了,程序要用內(nèi)存的時候直接從棧上分配就行了,也不會有碎片。  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 10:18 zuhd

            1,“最大的問題是如何判斷一個對象已經(jīng)不再被使用了”
            自己分配的內(nèi)存,自己不知道什么時候釋放嗎?
            2,“初步的想法是通過棧地址,找到其上所指的堆地址,對于不在其列的堆地址,將其從堆中移除(標記為待回收)”
            這句話的意思是?  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 10:30 volnet

            @pcm
            我的意思是,在堆中,存放的是一個對象的真實內(nèi)容,在棧中存在的是存放對象內(nèi)容的堆的地址,也就是一個int *p,這樣,那么如果p的值在已經(jīng)不在棧中了,也就是我這個管理器中還存有這個地址的相關(guān)內(nèi)存的話,其實這塊內(nèi)存將不再被引用,就被標記為垃圾了。  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 10:31 volnet

            @zuhd
            1、就像new和delete所面臨的挑戰(zhàn)一樣,我們能保證用的時候去分配,但是通常可能因為一些原因忘記去釋放這塊內(nèi)存,比如你已經(jīng)很小心了,但是異常出現(xiàn)的時候,可能delete并沒有執(zhí)行。
            2、詳見上一條回復(fù)  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 15:08 volnet

            移除prev_chunk,next_chunk,新增near_chunk,修改remove_chunk
            方法有更新,更新內(nèi)容:

            BOOL memory_manager::near_chunk(block_table_type &list, int offset, OUT chunk_type * prevChunk, OUT chunk_type * nextChunk)
            {
            block_table_type::iterator itPrev;
            block_table_type::iterator itNext;

            if(prevChunk == 0 || nextChunk == 0)
            return FALSE;
            else
            {
            prevChunk->status = Occupied;
            nextChunk->status = Occupied;
            }
            if(list[offset].hHeap == 0)
            return FALSE;
            block_table_type::iterator it = list.find(offset);
            if(it == list.end())
            return FALSE;

            itPrev = list.end();
            itNext = list.end();

            if(it != list.begin())
            {
            itPrev = --it;
            ++it;
            }

            if(it != list.end())
            {
            itNext = ++it;
            --it;
            }

            if(itPrev != list.end())
            {
            prevChunk->hHeap = (itPrev)->second.hHeap;
            prevChunk->pHead = (itPrev)->second.pHead;
            prevChunk->size = (itPrev)->second.size;
            prevChunk->status = (itPrev)->second.status;
            }

            if(itNext != list.end())
            {
            nextChunk->hHeap = (itNext)->second.hHeap;
            nextChunk->pHead = (itNext)->second.pHead;
            nextChunk->size = (itNext)->second.size;
            nextChunk->status = (itNext)->second.status;
            }
            if(itPrev != list.end() || itNext != list.end())
            return TRUE;
            return FALSE;
            }
            void remove_chunk(int heapIndex, int offset)
            {
            chunk_type prevFreeChunk, nextFreeChunk;
            if( near_chunk(heap_list[heapIndex].full_list, offset, &prevFreeChunk, &nextFreeChunk) )
            {
            // a) 前項檢測:
            // 前一項如果為Free,將前項size+=當前項size,刪除當前項。
            if(prevFreeChunk.status == Free && nextFreeChunk.status != Free)
            {
            int prevOffset = static_cast(prevFreeChunk.pHead) - static_cast(heap_list[heapIndex].pHead);
            free_chunk_list_remove(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
            heap_list[heapIndex].full_list[prevOffset].size += heap_list[heapIndex].full_list[offset].size;
            free_chunk_list_add(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
            int eraseSucceed = heap_list[heapIndex].full_list.erase(offset);
            #ifdef _DEBUG
            // 如果移除偏移不等于1個
            if( eraseSucceed != 1)
            {
            _TRACE(_W("從完全列表中移除對象出現(xiàn)異常,移除offset為%d,移除個數(shù)為%d.\n"), offset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行前項檢測且前項狀態(tài)為空閑,可執(zhí)行合并。前項偏移為%d\n"), prevOffset);
            #endif
            }

            // b) 后項檢測:
            // 如果后項為Free,將當前項size=size+后項size,刪除后項。
            else if(prevFreeChunk.status != Free && nextFreeChunk.status == Free)
            {
            int nextOffset = static_cast(nextFreeChunk.pHead) - static_cast(heap_list[heapIndex].pHead);
            free_chunk_list_remove(heap_list[heapIndex].full_list[nextOffset].size, heap_list[heapIndex].hHeap);
            heap_list[heapIndex].full_list[offset].size += heap_list[heapIndex].full_list[nextOffset].size;
            free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            int eraseSucceed = heap_list[heapIndex].full_list.erase(nextOffset);
            #ifdef _DEBUG
            // 如果移除偏移不等于1個
            if( eraseSucceed != 1)
            {
            _TRACE(_W("從完全列表中移除對象出現(xiàn)異常,移除nextOffset為%d,移除個數(shù)為%d.\n"), nextOffset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行后項檢測且后項狀態(tài)為空閑,可執(zhí)行合并。后項偏移為%d\n"), nextOffset);
            #endif
            return;
            }

            // c) 前后項檢測:
            else if(prevFreeChunk.status == Free && nextFreeChunk.status == Free)
            {
            int prevOffset = static_cast(prevFreeChunk.pHead) - static_cast(heap_list[heapIndex].pHead);
            int nextOffset = static_cast(nextFreeChunk.pHead) - static_cast(heap_list[heapIndex].pHead);
            free_chunk_list_remove(heap_list[heapIndex].full_list[nextOffset].size, heap_list[heapIndex].hHeap);
            free_chunk_list_remove(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
            heap_list[heapIndex].full_list[prevOffset].size
            = heap_list[heapIndex].full_list[prevOffset].size
            + heap_list[heapIndex].full_list[offset].size
            + heap_list[heapIndex].full_list[nextOffset].size;
            free_chunk_list_add(heap_list[heapIndex].full_list[prevOffset].size, heap_list[heapIndex].hHeap);
            int eraseSucceed = heap_list[heapIndex].full_list.erase(offset);
            eraseSucceed += heap_list[heapIndex].full_list.erase(nextOffset);
            #ifdef _DEBUG
            // 如果移除偏移不等于2個
            if( eraseSucceed != 2)
            {
            _TRACE(_W("從完全列表中移除對象出現(xiàn)異常,移除offset為%d,移除nextOffset為%d,移除個數(shù)為%d.\n"), offset, nextOffset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行前后項檢測且前后項狀態(tài)為空閑,可執(zhí)行合并。\n"));
            #endif
            return;
            }
            // d) 前后項檢測:
            else if(prevFreeChunk.status == Occupied && nextFreeChunk.status == Occupied)
            {
            free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            else
            {
            _TRACE(_W("該情況不在考慮范圍內(nèi)。\n"));
            }
            }
            else
            {
            free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            }  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-07 15:15 volnet

            已經(jīng)更新下載代碼中的測試用例,現(xiàn)在的測試更加復(fù)雜,更具有一般性,歡迎大家下載體驗,程序有些許改動,詳見上一條回復(fù):
            [移除prev_chunk,next_chunk,新增near_chunk,修改remove_chunk]
            源代碼下載地址不變。
            源代碼下載:
            http://m.shnenglu.com/Files/mymsdn/memory_manager.rar  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-08 10:51 zuhd

            @volnet
            1,那你說的這個是智能指針,貌似與你的主題有點偏離,好吧,就算加入智能指針,那么你要自己寫這個智能指針了,以為你的析構(gòu)并不是把內(nèi)存回收給系統(tǒng),而是回收到池。
            2,在堆中分配內(nèi)存的地址,你保存到哪里不重要,只是個數(shù)據(jù)而已。重要的是你想做智能指針,那么你就要做引用計數(shù),參考vczh的一片文章吧。
            另:參考SGI的stl的allocator,對你有幫助的  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-08 11:07 volnet

            @zuhd
            感謝您的回復(fù)。
            1、我和智能指針要解決的應(yīng)該是相同的問題,另外我還希望能夠解決一些碎片相關(guān)的問題,雖然現(xiàn)在還沒有做具體的代碼和設(shè)計。但是如果我接管了new或者部分new的話,我就有辦法去管理它們,并且動一點手腳了。現(xiàn)在關(guān)于是否每個分配都有正確的釋放,這一點我暫時不做太多考慮了,我們現(xiàn)在基本用shared_ptr來做,這里就有一個問題了,我希望用我的內(nèi)存分配機制去替換shared_ptr的對象存儲。考慮下面的代碼shared_ptr sp_(new MyClass()); 其實內(nèi)存還是通過默認的operator new去分配的內(nèi)存,這個內(nèi)存通常是直接向操作系統(tǒng)去調(diào)用的,我現(xiàn)在希望有一塊較大的內(nèi)存,然后所有小塊的內(nèi)存分配我都希望自己來管理,而不用每次都向操作系統(tǒng)申請。但是現(xiàn)在shared_ptr在發(fā)揮作用前就已經(jīng)通過new去做了內(nèi)存分配,顯然我自造shared_ptr是無法解決這個問題的。我不知道有沒有辦法轉(zhuǎn)存那塊內(nèi)存,并立即釋放掉,比如在內(nèi)部通過memmove將向系統(tǒng)new出來的部分拷貝到我的構(gòu)造中,然后將它們釋放,這樣我就不用替換全局的new來管理與shared_ptr有關(guān)的內(nèi)存了。因為我們的代碼中大部分用到了shared_ptr,所以此法能解決比較多的問題。
            2、是否有其他的建議呢?  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-08 11:08 volnet

            @zuhd
            因為我的代碼用到STL的東西,所以現(xiàn)在替換全局new,似乎還有問題……悲劇  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-08 14:11 立清

            SGI STL memory allocator源碼對memory pool有很好的實現(xiàn)。  回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-07-09 10:34 zuhd

            @volnet
            但是現(xiàn)在shared_ptr在發(fā)揮作用前就已經(jīng)通過new去做了內(nèi)存分配,顯然我自造shared_ptr是無法解決這個問題的。

            So....?
            1,從系統(tǒng)獲得的內(nèi)存你來管理,不管是申請還是釋放
            2,你實現(xiàn)一個智能指針,他暴露出來的僅僅是智能,也就是說他的內(nèi)存釋放是不用關(guān)心的,至于智能指針的內(nèi)存是從系統(tǒng)獲得的還是從你的池中獲得的,別于外面是不可知的,也是無需關(guān)心的
            所以這兩個概念不能搞混淆了,也許你最終實現(xiàn)的是一個在內(nèi)存池的基礎(chǔ)上造一個智能指針

              回復(fù)  更多評論   

            # re: [C++]內(nèi)存管理(1) 2010-08-29 17:29 evening dresses

            的機制,最大的問題是如何判斷一個對象已經(jīng)不再被使用了?初步的想法是通過棧地址,找到其上所指的堆地址,對于不在其列的堆地址,將其從堆中移除(標記為待回收)。對以下幾個問題存在疑問:  回復(fù)  更多評論   

            特殊功能
             
            亚洲国产精品综合久久网络 | 国产精品乱码久久久久久软件| 久久综合综合久久狠狠狠97色88| 国产精品免费久久久久影院| 日韩亚洲国产综合久久久| 区久久AAA片69亚洲| 国产亚洲精久久久久久无码| 精品久久久久国产免费| 少妇久久久久久被弄高潮| 精品久久久无码中文字幕天天| 色青青草原桃花久久综合| 久久婷婷久久一区二区三区| 一本大道久久东京热无码AV| 97久久久精品综合88久久| 久久这里只有精品首页| 精品国产婷婷久久久| 国产Av激情久久无码天堂| 精品综合久久久久久98| 国产成人精品综合久久久| 久久亚洲AV成人无码电影| 欧美精品乱码99久久蜜桃| 久久久久久久综合日本| 99久久精品免费看国产| 99久久久国产精品免费无卡顿| 久久亚洲AV永久无码精品| 欧美激情精品久久久久| 狠狠色丁香久久婷婷综合五月| 久久精品人人做人人爽电影 | 久久久久人妻精品一区| 国产99久久久国产精品小说| 久久99精品国产麻豆婷婷| 久久综合综合久久狠狠狠97色88| 久久国产高潮流白浆免费观看| 伊人久久大香线焦AV综合影院| 亚洲精品综合久久| 久久久久久久国产免费看| 免费一级欧美大片久久网| 久久免费香蕉视频| 久久久黄色大片| 国产A级毛片久久久精品毛片| 国产精品亚洲综合久久|