• <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記錄開發新知道

            [C++]內存管理(1)

            和大多數內存管理的初衷一致,希望能夠控制內存分配和回收,減少內存碎片,且通常這樣的內存都會預開一段連續內存空間,然后我們自己來管理這段內存。當然通常這樣的需求都很合理,但是實現起來則通常不能完美,比如:效率、算法的選擇、如何減少內存碎片、跟蹤管理內存分配、性能檢測、對系統內存使用的統計、垃圾回收等。下面是我近期實現的一個非常簡陋的程序,甚至可能連基本的要求都無法達到,大家幫忙看看,它究竟有多少缺點需要被注意和改進,哪些是無法容忍的?

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

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

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

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

            詳細設計:

            內存管理

            目的

            方法

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

            二、凌駕于多個堆之上的數據結構:所有結構可以反查屬于哪個堆。

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

            每個節點應該包含以下信息:

            i. 空閑區塊的尺寸;

            ii. 空閑區塊所屬的堆;

            為了優化查詢搜索,這里將相同尺寸歸并,并列出對應堆和每個堆上該尺寸的區塊的大小:

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

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

            每個節點應該包含以下信息:

            i. 堆的句柄;

            1. 連續內存空間的一塊堆內存,用來存儲數據值。

            ii. 堆的最大可用區塊空間;

            iii. 堆的最小可用區塊空間;

            iv. 用于管理堆的內部區域鏈表:

            1. 一個完整堆內區塊鏈表,按照地址升序存放。

            鏈表的每個節點,代表每一個獨立的內存區塊,區塊是用戶申請的最小粒度。每個節點應該包含以下信息:

            a) 區塊的尺寸;

            b) 區塊的狀態(未格式化,空閑,占用);

            c) 區塊的首地址指針;

            為了優化查詢搜索,這里也可用map:

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

            三、內部計數器,用于診斷和性能分析,碎片分析

            a) 分配次數計數器

            b) 分配成功次數計數器

            四、如何快速查找可分配區塊,并分配內存?

            輸入:預分配區塊尺寸

            輸出:指向預分配區塊的指針

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

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

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

            4、 針對找到的內存塊執行后續操作(包括:插入鏈表、修改原始節點尺寸/狀態、將內存塊首地址和對應堆更新到映射表中,更新內存塊尺寸表(根據找到的區塊的尺寸和區塊所屬堆來找,將其更新或移除)等);

            5、 返回對應指針。

            五、釋放內存塊

            輸入:void*內存塊指針

            輸出:BOOL

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

            2、 查找該堆對應的完整列表,找到該堆的節點,修改該節點的狀態為Free;

            3、 合并相鄰項,[該步驟的執行導致該鏈表中不存在兩塊連續的Free區塊]。

            a) 前項檢測:

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

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

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

            4、 更新內存尺寸表。

            5、 更新內存堆映射表。

            源碼:

            memory_manager_def.h

            /*
            說明:定義與內存管理相關的常量
            */
            
            #pragma once
            
            #include "stdafx.h"
            #include <map>
            
            /*堆的最大數量*/
            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的時候,被定義為碎片
            
            /*同一塊內存區域之間,兩個指針之間的偏移量*/
            typedef unsigned long offset_type;
            typedef unsigned char* byte_ptr_type;
            
            typedef enum _CHUNK_STATUS{ 
                Unformated,
                Free,
                Occupied
            } CHUNK_STATUS;
            
            

            memory_manager.h

            /*
            說明:定義內存管理接口
            */
            
            #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;
            
            /*內存尺寸表*/
            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:是指一個內存固定區塊內的一個可分配內存區塊*/
            typedef struct _chunk_type
            {
                _chunk_type():size(0), status(Free), hHeap(0), pHead(0){}
                size_t size;
                /*當前區塊的狀態*/
                CHUNK_STATUS status;
                /*當前區塊所屬的堆*/
                HANDLE hHeap;
                /*當前區塊的首地址*/
                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:是指一個內存固定區塊*/
            typedef struct _block_type
            {
                _block_type():hHeap(0)
                    //, max_free_chunk_size(0),min_free_chunk_size(0)
                {}
                HANDLE hHeap;
                ///*當前內存塊中剩余的最大塊尺寸(狀態為Free)*/
                //size_t max_free_chunk_size;
                ///*當前內存塊中剩余的最小塊尺寸*/
                //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];
                /*當從程序里返回內存塊的時候,記錄內存塊與堆的對應關系,當釋放的時候,取出對應的堆*/
                chunk_heap_table_type chunk_heap_table;
                /*一個用于描述所有堆能夠存放的內存塊(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

            /*
            說明:定義內存管理的實現部分
            */
            #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、    如果預分配尺寸大于單塊固定堆尺寸,返回NULL;
                if( size > HEAP_SIZE)
                {
                    _TRACE(_W("申請內存尺寸%d > 單區內存最大尺寸%d.\n"), size, HEAP_SIZE);
                    return 0;
                }
                else if(size == 0)
                {
                    _TRACE(_W("申請內存尺寸為%d.\n"), size);
                    return 0;
                }
            
                // 2、    查詢內存塊尺寸表,查找最合適的(尺寸>=預分配尺寸的最接近內存塊,如果是大于的情況)內存塊,返回其所屬的堆句柄;
                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、    找到對應堆的內部區域鏈表,順序查找最合適的內存塊(條件和前述相同);作為調試信息的一部分,判斷,如果查找不到內存塊該內存塊,則完全同步一次堆剩余尺寸到區域尺寸映射表(如果該方案的失敗率過高,則應該廢除該方法)
                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、    針對找到的內存塊執行后續操作(包括:插入鏈表、修改原始節點尺寸/狀態、將內存塊首地址和對應堆更新到映射表中,更新內存塊尺寸表(根據找到的區塊的尺寸和區塊所屬堆來找,將其更新或移除)等);
                           
                            it->second.status = Occupied;
                            mem = it->second.pHead;
                            hHeap = it->second.hHeap;
                            removeSize = it->second.size;
            
                            // 從內存塊尺寸表中,移除該塊內存
                            free_chunk_list_remove(removeSize, hHeap);
                        }
                        else /*if(it->second.size > size)*/
                        {
                            // 4、    針對找到的內存塊執行后續操作(包括:插入鏈表、修改原始節點尺寸/狀態、將內存塊首地址和對應堆更新到映射表中,更新內存塊尺寸表(根據找到的區塊的尺寸和區塊所屬堆來找,將其更新或移除)等);
                            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("此塊內存塊大小為%d、即將分配%d、分配完后將剩%d、左側空閑塊偏移%d、右側即將分配的塊偏移%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;
            
                            // 從內存塊尺寸表中,
                            // 1、移除原始尺寸模塊;
                            // 2、增加新的可用內存塊;
                            free_chunk_list_remove(originalSize, hHeap);
                            free_chunk_list_add(restSize, hHeap);
                        }
                        break;
                    }
                }
            
                // 將當前選中的內存塊存進映射表中
                set_chunk_heap(mem, hHeap);
            
                // 5、    返回對應指針。
                return mem;
            }
            
            void memory_manager::deallocate(void * ptr)
            {
                // 1、    查表確定該內存塊屬于哪個堆?返回堆句柄;
                HANDLE hHeap = which_heap(ptr);
                size_t deallocateSize;
                if(hHeap == 0)
                {
            #ifdef _DEBUG
                    _TRACE(_W("所訪問指針不在可管理的堆中.\n"));
            #endif
                }
                else
                {
                    // 2、    查找該堆對應的完整列表,找到該堆的節點,修改該節點的狀態為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("刪除的內存塊偏移為%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("所訪問的指針狀態不是已占用,原則上應該是已占用.\n"));
                    }
            #endif
                    heap_list[index].full_list[offset].status = Free;
                    
                    // 3、    合并相鄰項,[該步驟的執行導致該鏈表中不存在兩塊連續的Free區塊]。
                    remove_chunk(heap_list[index].full_list, index, offset);
            
                    // 4、    更新內存尺寸表。
                    // 已經包含在remove_chunk中
            
                    // 5、 更新內存堆映射表。
                    remove_chunk_heap(ptr);
                }
            }
            
            /*輸出某一瞬間的各列表信息
            */
            void memory_manager::debug_snapshot(void)
            {
            #ifdef _DEBUG
                _TRACE(_W("-----------start snapshot-------------\n"));
                _TRACE(_W("內存塊尺寸表:\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("    從“內存塊尺寸表”來看,總共有%d塊空閑內存,其中碎片(<= %d byte)的內存塊有%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];
                            // 碎片數量
                            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"));
                    _TRACE(_W("    第%d塊堆擁有%d空閑內存、%d已占內存、%d碎片\n"), i, heapListItemFreeCounter[i], heapListItemOccupidCounter[i], heapListItemFragmentCounter[i]);
            
                    heapListItemTotalFreeCounter += heapListItemFreeCounter[i];
                    heapListItemTotalOccupidCounter +=heapListItemOccupidCounter[i];
                    heapListItemTotalFragmentCounter +=heapListItemFragmentCounter[i];
                    heapListItemTotalCounter += heapListItemCounter[i];
                }
                _TRACE(_W("所有堆中共有%d內存塊、%d空閑內存、%d已占內存、%d碎片\n"), 
                    heapListItemTotalCounter,
                    heapListItemTotalFreeCounter,  
                    heapListItemTotalOccupidCounter,
                    heapListItemTotalFragmentCounter);
            
                _TRACE(_W("------------end  snapshot-------------\n"));
            #endif
            }
            
            /*堆初始化(全部)
            策略:
                1、設置堆列表中的堆句柄為、最大可用尺寸為、最小可用尺寸為、可分配內存首地址為
                */
            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、初始化堆各個字段,并對堆實行完全內存分配。其中堆尺寸、最大最小可用尺寸均為完全分配尺寸
            */
            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
            /*創建堆對象
            策略:
                1、創建一個固定大小的堆
                2、啟用LFH以減小內存碎片(如果允許的話)
            */
            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)
                // 以減少內存碎片
            #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);
            }
            /*申請內存塊
            策略:
            */
            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;
            }
            
            /*釋放內存塊
            參數:
                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("執行前項檢測且前項狀態為空閑,可執行合并。前項偏移為%d\n"), prevOffset);
            #endif
                        return;
                    }
                }
            
                chunk_type nextFreeChunk;
                // b)    后項檢測:(如果前項檢測無結果)
                // 如果后項為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("執行后項檢測且后項狀態為空閑,可執行合并。后項偏移為%d\n"), nextOffset);
            #endif
                        return;
                    }
                }
                free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            
            /*
            查詢堆信息,輔助調試,可以查看當前堆的特性
            */
            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
            
            /*向內存尺寸表中添加尺寸信息
            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;
                    }
                }
            
                // 否則如果沒有找到該堆所對應的相同尺寸的信息
                free_chunk freeChunk;
                freeChunk.count = 1;
                freeChunk.hHeap = hHeap;
            
                free_chunk_table.insert(std::make_pair(size, freeChunk)); // copy 
            }
            
            /*從內存尺寸表中移除尺寸信息
            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("從內存尺寸表中查找size=%d的內存時候,無法找到記錄.\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("從內存尺寸表中查找size=%d的內存時候,無法找到記錄.\n"), size);
            #endif // _DEBUG
            }
            
            /*通過可用鏈表查詢可用的內存區塊
            策略:
                1、遍歷可用區塊鏈表(該鏈表已經按尺寸從小到大順序排列)
                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"));
            #endif
                    }
                }
            
                return FALSE;
            }
            
            /*某個任意指針屬于哪個堆,返回值為表示不是在堆列表中的堆
            策略:
            1、本設計中存在返回指針以及所屬指針的字典映射
            2、通過查表法找出當前指針所屬的堆信息
            */
            HANDLE memory_manager::which_heap(void * ptr)
            {
                HANDLE hHeap = chunk_heap_table[ptr];
                if( NULL == hHeap )
                {
                    _TRACE(_W("該指針不屬于任意內存塊.\n"));
                    return 0;
                }
                else
                {
            #ifdef _DEBUG
                    _TRACE(_W("當前使用的指針來自第%d塊堆.\n"), heap_index(hHeap));
            #endif
                    return hHeap;
                }
            }
            
            /*將指針和對應堆信息存進字典備查
            策略:
            1、本設計中存在返回指針以及所屬指針的字典映射
            2、以指針作為鍵值,將對應堆句柄作為值
            */
            void memory_manager::set_chunk_heap(void * ptr, HANDLE hHeap)
            {
            #ifdef _DEBUG
                if(chunk_heap_table[ptr] != 0)
                {
                    _TRACE(_W("在此之前已經有相同的指針存在于表中,還未釋放.\n"));
                    return;
                }
            #endif  
                chunk_heap_table[ptr] = hHeap;
            }
            
            /*將指針和對應堆信息移出字典
            策略:
            1、本設計中存在返回指針以及所屬指針的字典映射
            2、當該指針作廢后,此處移走對應項
            */
            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已經從第%d塊堆中移除.\n"), ptr, heap_index( hHeap ));
            #endif  
            }

            memory_manager_main.cpp

            // memory_manager.cpp : 定義控制臺應用程序的入口點。
            //
            
            #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);
                    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("累計申請內存數量%d、申請%d次、申請的最大內存為%d。\n"), totalMemory, curr, max);
            
                mm.debug_snapshot();
                _TRACE(_W("====================開始釋放內存。\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) 評論(17)  編輯 收藏 引用 所屬分類: C/C++

            評論

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

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

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

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

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

            源代碼下載:
            http://www.shnenglu.com/Files/mymsdn/memory_manager.rar  回復  更多評論   

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

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

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

            @OwnWaterloo
            希望您多指教啊  回復  更多評論   

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

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

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

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

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

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

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

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

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

            移除prev_chunk,next_chunk,新增near_chunk,修改remove_chunk
            方法有更新,更新內容:

            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("從完全列表中移除對象出現異常,移除offset為%d,移除個數為%d.\n"), offset, eraseSucceed);
            }
            _TRACE(_W("執行前項檢測且前項狀態為空閑,可執行合并。前項偏移為%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("從完全列表中移除對象出現異常,移除nextOffset為%d,移除個數為%d.\n"), nextOffset, eraseSucceed);
            }
            _TRACE(_W("執行后項檢測且后項狀態為空閑,可執行合并。后項偏移為%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("從完全列表中移除對象出現異常,移除offset為%d,移除nextOffset為%d,移除個數為%d.\n"), offset, nextOffset, eraseSucceed);
            }
            _TRACE(_W("執行前后項檢測且前后項狀態為空閑,可執行合并。\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"));
            }
            }
            else
            {
            free_chunk_list_add(heap_list[heapIndex].full_list[offset].size, heap_list[heapIndex].hHeap);
            }
            }  回復  更多評論   

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

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

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

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

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

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

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

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

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

            SGI STL memory allocator源碼對memory pool有很好的實現。  回復  更多評論   

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

            @volnet
            但是現在shared_ptr在發揮作用前就已經通過new去做了內存分配,顯然我自造shared_ptr是無法解決這個問題的。

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

              回復  更多評論   

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

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

            特殊功能
             
            久久久青草青青亚洲国产免观| 一本久久a久久精品亚洲| 99久久精品国产一区二区| 久久中文娱乐网| 99久久精品费精品国产一区二区 | 久久婷婷五月综合色奶水99啪| 久久男人中文字幕资源站| 久久亚洲国产成人精品无码区| 色婷婷噜噜久久国产精品12p| 久久精品综合网| 一本久久a久久精品亚洲| 久久国产欧美日韩精品免费| 三级三级久久三级久久| 色播久久人人爽人人爽人人片AV| 成人妇女免费播放久久久| 亚洲伊人久久大香线蕉苏妲己| 精品国产婷婷久久久| 欧美粉嫩小泬久久久久久久| 久久精品国产亚洲AV不卡| 伊人色综合久久天天人手人婷 | 狠狠色丁香婷婷综合久久来| 国产日产久久高清欧美一区| 色综合久久中文色婷婷| 久久人人爽人人爽人人片AV麻豆| 久久久www免费人成精品| 久久精品无码专区免费青青| 久久久WWW成人| 久久精品国产亚洲AV久| 久久婷婷色综合一区二区| 久久大香萑太香蕉av| 精品国产一区二区三区久久| 久久久久九国产精品| 麻豆一区二区99久久久久| 91精品国产91久久久久久青草 | 国产精品久久成人影院| 青青青青久久精品国产| 久久精品一区二区三区AV| 一级a性色生活片久久无| 99久久国产主播综合精品| 久久精品一本到99热免费| 久久九九久精品国产免费直播|