• <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)存都會(huì)預(yù)開一段連續(xù)內(nèi)存空間,然后我們自己來(lái)管理這段內(nèi)存。當(dāng)然通常這樣的需求都很合理,但是實(shí)現(xiàn)起來(lái)則通常不能完美,比如:效率、算法的選擇、如何減少內(nèi)存碎片、跟蹤管理內(nèi)存分配、性能檢測(cè)、對(duì)系統(tǒng)內(nèi)存使用的統(tǒng)計(jì)、垃圾回收等。下面是我近期實(shí)現(xiàn)的一個(gè)非常簡(jiǎn)陋的程序,甚至可能連基本的要求都無(wú)法達(dá)到,大家?guī)兔纯矗烤褂卸嗌偃秉c(diǎn)需要被注意和改進(jìn),哪些是無(wú)法容忍的?

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

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

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

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

            詳細(xì)設(shè)計(jì):

            內(nèi)存管理

            目的

            方法

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

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

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

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

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

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

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

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

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

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

            i. 堆的句柄;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            輸出:BOOL

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

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

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

            a) 前項(xiàng)檢測(cè):

            前一項(xiàng)如果為Free,將前項(xiàng)size+=當(dāng)前項(xiàng)size,刪除當(dāng)前項(xiàng)。

            b) 后項(xiàng)檢測(cè):(如果前項(xiàng)檢測(cè)無(wú)結(jié)果)

            如果后項(xiàng)為Free,將當(dāng)前項(xiàng)size=size+后項(xiàng)size,刪除后項(xiàng)。

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

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

            源碼:

            memory_manager_def.h

            /*
            說(shuō)明:定義與內(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; // 當(dāng)小于byte的時(shí)候,被定義為碎片
            
            /*同一塊內(nèi)存區(qū)域之間,兩個(gè)指針之間的偏移量*/
            typedef unsigned long offset_type;
            typedef unsigned char* byte_ptr_type;
            
            typedef enum _CHUNK_STATUS{ 
                Unformated,
                Free,
                Occupied
            } CHUNK_STATUS;
            
            

            memory_manager.h

            /*
            說(shuō)明:定義內(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:是指一個(gè)內(nèi)存固定區(qū)塊內(nèi)的一個(gè)可分配內(nèi)存區(qū)塊*/
            typedef struct _chunk_type
            {
                _chunk_type():size(0), status(Free), hHeap(0), pHead(0){}
                size_t size;
                /*當(dāng)前區(qū)塊的狀態(tài)*/
                CHUNK_STATUS status;
                /*當(dāng)前區(qū)塊所屬的堆*/
                HANDLE hHeap;
                /*當(dāng)前區(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:是指一個(gè)內(nèi)存固定區(qū)塊*/
            typedef struct _block_type
            {
                _block_type():hHeap(0)
                    //, max_free_chunk_size(0),min_free_chunk_size(0)
                {}
                HANDLE hHeap;
                ///*當(dāng)前內(nèi)存塊中剩余的最大塊尺寸(狀態(tài)為Free)*/
                //size_t max_free_chunk_size;
                ///*當(dāng)前內(nèi)存塊中剩余的最小塊尺寸*/
                //size_t min_free_chunk_size;
                size_t size;
                block_table_type full_list;
                /*當(dāng)前堆的首地址*/
                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];
                /*當(dāng)從程序里返回內(nèi)存塊的時(shí)候,記錄內(nèi)存塊與堆的對(duì)應(yīng)關(guān)系,當(dāng)釋放的時(shí)候,取出對(duì)應(yīng)的堆*/
                chunk_heap_table_type chunk_heap_table;
                /*一個(gè)用于描述所有堆能夠存放的內(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

            /*
            說(shuō)明:定義內(nèi)存管理的實(shí)現(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("申請(qǐng)內(nèi)存尺寸%d > 單區(qū)內(nèi)存最大尺寸%d.\n"), size, HEAP_SIZE);
                    return 0;
                }
                else if(size == 0)
                {
                    _TRACE(_W("申請(qǐng)內(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、    找到對(duì)應(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、    針對(duì)找到的內(nèi)存塊執(zhí)行后續(xù)操作(包括:插入鏈表、修改原始節(jié)點(diǎn)尺寸/狀態(tài)、將內(nèi)存塊首地址和對(duì)應(yīng)堆更新到映射表中,更新內(nèi)存塊尺寸表(根據(jù)找到的區(qū)塊的尺寸和區(qū)塊所屬堆來(lái)找,將其更新或移除)等);
                           
                            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、    針對(duì)找到的內(nèi)存塊執(zhí)行后續(xù)操作(包括:插入鏈表、修改原始節(jié)點(diǎn)尺寸/狀態(tài)、將內(nèi)存塊首地址和對(duì)應(yīng)堆更新到映射表中,更新內(nèi)存塊尺寸表(根據(jù)找到的區(qū)塊的尺寸和區(qū)塊所屬堆來(lái)找,將其更新或移除)等);
                            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;
                    }
                }
            
                // 將當(dāng)前選中的內(nèi)存塊存進(jìn)映射表中
                set_chunk_heap(mem, hHeap);
            
                // 5、    返回對(duì)應(yīng)指針。
                return mem;
            }
            
            void memory_manager::deallocate(void * ptr)
            {
                // 1、    查表確定該內(nèi)存塊屬于哪個(gè)堆?返回堆句柄;
                HANDLE hHeap = which_heap(ptr);
                size_t deallocateSize;
                if(hHeap == 0)
                {
            #ifdef _DEBUG
                    _TRACE(_W("所訪問指針不在可管理的堆中.\n"));
            #endif
                }
                else
                {
                    // 2、    查找該堆對(duì)應(yīng)的完整列表,找到該堆的節(jié)點(diǎn),修改該節(jié)點(diǎn)的狀態(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("所訪問的指針在可管理堆中無(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、    合并相鄰項(xiàng),[該步驟的執(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個(gè).\n"), cIter->second.hHeap, cIter->first, cIter->second.count);
                    ++totalFreeCounter;
                    if(cIter->first <= FRAGMENT_SIZE)
                        fragmentCounter+=cIter->second.count;
                }
                _TRACE(_W("    從“內(nèi)存塊尺寸表”來(lái)看,總共有%d塊空閑內(nèi)存,其中碎片(<= %d byte)的內(nèi)存塊有%d個(gè).\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;
                }
            }
            
            /*堆初始化(單個(gè))
            策略:
                1、初始化堆各個(gè)字段,并對(duì)堆實(shí)行完全內(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)建堆對(duì)象
            策略:
                1、創(chuàng)建一個(gè)固定大小的堆
                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;
            }
            
            /*釋放堆對(duì)象*/
            inline BOOL memory_manager::heap_destroy_base(HANDLE hHeap)
            {
                return HeapDestroy(hHeap);
            }
            /*申請(qǐng)內(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);
            }
            
            /*查找某個(gè)堆屬于堆列表中的第幾個(gè)
            */
            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)    前項(xiàng)檢測(cè):
                // 前一項(xiàng)如果為Free,將前項(xiàng)size+=當(dāng)前項(xiàng)size,刪除當(dāng)前項(xiàng)。
                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í)行前項(xiàng)檢測(cè)且前項(xiàng)狀態(tài)為空閑,可執(zhí)行合并。前項(xiàng)偏移為%d\n"), prevOffset);
            #endif
                        return;
                    }
                }
            
                chunk_type nextFreeChunk;
                // b)    后項(xiàng)檢測(cè):(如果前項(xiàng)檢測(cè)無(wú)結(jié)果)
                // 如果后項(xiàng)為Free,將當(dāng)前項(xiàng)size=size+后項(xiàng)size,刪除后項(xiàng)。
                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í)行后項(xiàng)檢測(cè)且后項(xiàng)狀態(tài)為空閑,可執(zhí)行合并。后項(xiàng)偏移為%d\n"), nextOffset);
            #endif
                        return;
                    }
                }
                free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            
            /*
            查詢堆信息,輔助調(diào)試,可以查看當(dāng)前堆的特性
            */
            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;
                    }
                }
            
                // 否則如果沒有找到該堆所對(duì)應(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)存時(shí)候,無(wú)法找到記錄.\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)存時(shí)候,無(wú)法找到記錄.\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;
            }
            
            /*某個(gè)任意指針屬于哪個(gè)堆,返回值為表示不是在堆列表中的堆
            策略:
            1、本設(shè)計(jì)中存在返回指針以及所屬指針的字典映射
            2、通過查表法找出當(dāng)前指針?biāo)鶎俚亩研畔?
            */
            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āng)前使用的指針來(lái)自第%d塊堆.\n"), heap_index(hHeap));
            #endif
                    return hHeap;
                }
            }
            
            /*將指針和對(duì)應(yīng)堆信息存進(jìn)字典備查
            策略:
            1、本設(shè)計(jì)中存在返回指針以及所屬指針的字典映射
            2、以指針作為鍵值,將對(duì)應(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;
            }
            
            /*將指針和對(duì)應(yīng)堆信息移出字典
            策略:
            1、本設(shè)計(jì)中存在返回指針以及所屬指針的字典映射
            2、當(dāng)該指針作廢后,此處移走對(duì)應(yīng)項(xià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 : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
            //
            
            #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("開始申請(qǐng)%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("累計(jì)申請(qǐng)內(nèi)存數(shù)量%d、申請(qǐng)%d次、申請(qǐng)的最大內(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 閱讀(3834) 評(píng)論(17)  編輯 收藏 引用 所屬分類: C/C++

            評(píng)論

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

            請(qǐng)教一下: 這個(gè)排版是怎么做的? live writter?  回復(fù)  更多評(píng)論   

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            @zuhd
            1、就像new和delete所面臨的挑戰(zhàn)一樣,我們能保證用的時(shí)候去分配,但是通常可能因?yàn)橐恍┰蛲浫メ尫胚@塊內(nèi)存,比如你已經(jīng)很小心了,但是異常出現(xiàn)的時(shí)候,可能delete并沒有執(zhí)行。
            2、詳見上一條回復(fù)  回復(fù)  更多評(píng)論   

            # 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) 前項(xiàng)檢測(cè):
            // 前一項(xiàng)如果為Free,將前項(xiàng)size+=當(dāng)前項(xiàng)size,刪除當(dāng)前項(xiàng)。
            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個(gè)
            if( eraseSucceed != 1)
            {
            _TRACE(_W("從完全列表中移除對(duì)象出現(xiàn)異常,移除offset為%d,移除個(gè)數(shù)為%d.\n"), offset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行前項(xiàng)檢測(cè)且前項(xiàng)狀態(tài)為空閑,可執(zhí)行合并。前項(xiàng)偏移為%d\n"), prevOffset);
            #endif
            }

            // b) 后項(xiàng)檢測(cè):
            // 如果后項(xiàng)為Free,將當(dāng)前項(xiàng)size=size+后項(xiàng)size,刪除后項(xiàng)。
            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個(gè)
            if( eraseSucceed != 1)
            {
            _TRACE(_W("從完全列表中移除對(duì)象出現(xiàn)異常,移除nextOffset為%d,移除個(gè)數(shù)為%d.\n"), nextOffset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行后項(xiàng)檢測(cè)且后項(xiàng)狀態(tài)為空閑,可執(zhí)行合并。后項(xiàng)偏移為%d\n"), nextOffset);
            #endif
            return;
            }

            // c) 前后項(xiàng)檢測(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個(gè)
            if( eraseSucceed != 2)
            {
            _TRACE(_W("從完全列表中移除對(duì)象出現(xiàn)異常,移除offset為%d,移除nextOffset為%d,移除個(gè)數(shù)為%d.\n"), offset, nextOffset, eraseSucceed);
            }
            _TRACE(_W("執(zhí)行前后項(xiàng)檢測(cè)且前后項(xiàng)狀態(tài)為空閑,可執(zhí)行合并。\n"));
            #endif
            return;
            }
            // d) 前后項(xiàng)檢測(cè):
            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ù)  更多評(píng)論   

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

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

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

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

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

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

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

            @zuhd
            因?yàn)槲业拇a用到STL的東西,所以現(xiàn)在替換全局new,似乎還有問題……悲劇  回復(fù)  更多評(píng)論   

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

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

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

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

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

              回復(fù)  更多評(píng)論   

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

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

            特殊功能
             
            伊人久久五月天| 久久精品中文字幕一区| 国产偷久久久精品专区| 久久青草国产手机看片福利盒子| 亚洲精品成人网久久久久久| 国产欧美一区二区久久| 亚洲精品乱码久久久久久蜜桃不卡| 91久久精品视频| 久久精品人人槡人妻人人玩AV| 亚洲日韩欧美一区久久久久我| 国产一级做a爰片久久毛片| 亚洲午夜无码久久久久| 欧美性大战久久久久久| 久久精品国产精品国产精品污| 亚洲午夜久久久久妓女影院| 久久久人妻精品无码一区| 久久夜色tv网站| 精品综合久久久久久97超人 | 少妇内射兰兰久久| 无码精品久久一区二区三区 | 亚洲欧洲中文日韩久久AV乱码| 久久免费精品视频| 国产精品久久久天天影视| 成人午夜精品无码区久久| 污污内射久久一区二区欧美日韩| 亚洲国产精品一区二区久久| 久久久久人妻精品一区| 久久精品中文字幕一区| 狠狠色丁香婷婷久久综合| 久久影视综合亚洲| 久久久久久国产精品美女| 激情五月综合综合久久69| 国产成人精品综合久久久| 亚洲国产精品久久久久婷婷软件| 国产成人综合久久综合| 久久久久久久久久久久中文字幕| 无遮挡粉嫩小泬久久久久久久| 久久精品国产乱子伦| 99久久精品免费看国产一区二区三区| 久久久久久久波多野结衣高潮 | 亚洲精品国产美女久久久|