一个C++的内存池和内存管理的实现(七)

CSDN的博客管理真烂。草稿箱里的文章又莫名其妙的没了。好吧,又得重写,细节实在没兴趣写第二遍了,真TM扫兴!

这几章是内存越界检查的。内存越界检查也有很多工具。并且程序员自己也可以在内存块后面加一个额外的保护页,再将页的属性设置为不可读写(VirtualAlloc、VirtualProtect),这样一旦访问到保护页,系统会抛出异常。但是对于大型的复杂软件,并且bug涉及到多线程,有一定随机性的话,这种方式以及其他很多工具可能都会无能为力。

从本质上说,如果程序员在每个用到指针的地方都做指针的范围判断,那么指针越界就不是个问题了。然而你无法保证程序员会这么做(可能没有任何一个程序员会这么做),因为这样无论是编程效率还是运行效率都太慢了。运行效率还好办,你可以在不需要做越界检查时(比如正式的发布版本)将这些判断语句去掉,这并不是一件困难的事情,用个宏开关就行了。然而在每个用到指针的地方都加范围判断实在是太繁琐了。

这里就可以用到C++的封装了。我们可以把指针封装在一个对象里,并且让这个对象表现的像个指针。如果你用过智能指针,那么对这个应该会比较熟悉。接下来,我们只要对所有的指针内容的访问通道进行封装,加入范围判断就可以了。这些访问通道包括*[]->。当然,还有一些指针的操作,比如+++-==!=等等等等。

不多说了,自己看程序吧。这些程序放在与内存池不同的一个头文件里。

    //
    // Reference structure
    // 
    struct SmartHeapMemData
    {
        DWORD_PTR m_pStartMemPtr;  // pointer to the starting address of the memeory block really being used in the app
        DWORD_PTR m_pEndMemPtr;  // pointer to the ending address of the memeory block really being used in the app
        int m_nRefCnt;  // reference count, to allow fast copy
    };

    // 
    // Smart heap memory pointer class
    // 
    template<typename T> class __declspec(dllexport) SmartHeapMemPtr
    {

    public:
        SmartHeapMemData* m_pData;
        T* m_pPtr;  // pointer currently being used in the app
        int m_nUnmanagedLen;  // length of the memory block externally allocated (e.g. by modules from third party)

    public:
        // Constructor
        SmartHeapMemPtr() : m_pData(0), m_pPtr(0), m_nUnmanagedLen(0) {};
        template<typename t2> SmartHeapMemPtr(const SmartHeapMemPtr<t2>& p) { if ((m_pData = p.m_pData) != 0) IncRef(); m_pPtr = (T*) p.m_pPtr; };
        SmartHeapMemPtr(const SmartHeapMemPtr& p) { if ((m_pData = p.m_pData) != 0) IncRef(); m_pPtr = p.m_pPtr; };
        SmartHeapMemPtr(const T* p) : m_pData(0), m_nUnmanagedLen(0) { *this = p; };

        // Destructor
        ~SmartHeapMemPtr() { Release(); };

        // Assignment operator
        SmartHeapMemPtr& operator=(const T* p)
        {
            if (m_pData)
                DecRef();
            m_pData = new SmartHeapMemData;
            m_pData->m_nRefCnt = 1;
            if (p)
            {
                m_pData->m_pStartMemPtr = (DWORD_PTR) p;
                PPREFIX pPrefix = IsManagedMemory((void*) p);
                if (pPrefix)
                {
                    m_pData->m_pEndMemPtr = m_pData->m_pStartMemPtr + pPrefix->d.pPostfix->nActualSize - 1;
                    if (pPrefix->d.nRefCnt == 0)  // not already assigned to a smart pointer, so the calling is something like "watever* p = new whatever(...)"
                        m_pData->m_nRefCnt ++;  // otherwise, the intelligenet garbage collection will do garbage collection even if there is no corresponding delete command
                    pPrefix->d.nRefCnt ++;
                }
                else
                    m_pData->m_pEndMemPtr = (DWORD_PTR) p + m_nUnmanagedLen - 1;
            }
            else
                m_pData->m_pStartMemPtr = m_pData->m_pEndMemPtr = 0;
            m_pPtr = (T*) p;
            return *this;
        };

        SmartHeapMemPtr& operator=(const SmartHeapMemPtr<T>& p)
        {
            if (m_pData)
            {
                if (m_pData == p.m_pData)  // already the same
                    goto SMART_HEAP_ASSIGN_END;
                DecRef();
            }
            if ((m_pData = p.m_pData) != 0)
                IncRef();
SMART_HEAP_ASSIGN_END:
            m_pPtr = p.m_pPtr;
            return *this;
        };

        // Set the unamanged length
        BOOL SetUnmanagedLength(const int nLen) 
        {
            if (IsManagedMemory((void*) m_pData->m_pStartMemPtr))
                return FALSE;
            m_nUnmanagedLen = nLen;
            m_pData->m_pEndMemPtr = m_pData->m_pStartMemPtr + nLen;
            return TRUE;
        };

        // Pointer like syntax and semantics
        inline T* operator->()
        {
            if ((DWORD_PTR) m_pPtr < m_pData->m_pStartMemPtr || (DWORD_PTR) m_pPtr > m_pData->m_pEndMemPtr + 1 - sizeof(T))  // 越界检查
                throw char("Pointer bounds error!");
            return m_pPtr;
        };
        inline T& operator*()
        {
            if ((DWORD_PTR) m_pPtr < m_pData->m_pStartMemPtr || (DWORD_PTR) m_pPtr > m_pData->m_pEndMemPtr + 1 - sizeof(T))  // 越界检查
                throw char("Pointer bounds error!");
            return *m_pPtr;
        };
        inline const T* operator->() const { return m_pPtr; };
        inline const T& operator*() const { return *m_pPtr; };

        // Comparision operators
        bool operator==(const T* p) const { return (p == m_pPtr); };
        bool operator!=(const T* p) const { return (p != m_pPtr); };
        bool operator==(const SmartHeapMemPtr& p) const { return (p.m_pPtr == m_pPtr); };
        bool operator!=(const SmartHeapMemPtr& p) const { return (p.m_pPtr != m_pPtr); };
        bool operator>(const SmartHeapMemPtr& p) const { return (m_pPtr > p.m_pPtr); };
        bool operator<(const SmartHeapMemPtr& p) const { return (m_pPtr < p.m_pPtr); };

        // Arithmetic operators
        SmartHeapMemPtr<T> operator+(const int n) { SmartHeapMemPtr<T> ret; ret.m_pData = m_pData; ret.IncRef(); ret.m_pPtr = m_pPtr + n; return ret; };
        const SmartHeapMemPtr<T> operator+(const int n) const { SmartHeapMemPtr<T> ret; ret.m_pData = m_pData; ret.IncRef(); ret.m_pPtr = m_pPtr + n; return ret; };
        SmartHeapMemPtr<T> operator-(const int n) { SmartHeapMemPtr<T> ret; ret.m_pData = m_pData; ret.IncRef(); ret.m_pPtr = m_pPtr - n; return ret; };
        const SmartHeapMemPtr<T> operator-(const int n) const { SmartHeapMemPtr<T> ret; ret.m_pData = m_pData; ret.IncRef(); ret.m_pPtr = m_pPtr - n; return ret; };

        template<typename t2> int operator-(SmartHeapMemPtr<t2> p) { return (int) ((DWORD_PTR) m_pPtr - (DWORD_PTR) p.m_pPtr); };
        template<typename t2> int operator-(const SmartHeapMemPtr<t2> p) const { return (DWORD_PTR) m_pPtr - (DWORD_PTR) p.m_pPtr; };

        // Compound assignment operators
        SmartHeapMemPtr<T> & operator+=(const int n) { m_pPtr += n; return *this; };
        SmartHeapMemPtr<T> & operator-=(const int n) { m_pPtr -= n; return *this; };
        SmartHeapMemPtr<T> & operator++() { m_pPtr ++; return *this; };
        SmartHeapMemPtr<T> & operator--() { m_pPtr --; return *this; };
        SmartHeapMemPtr<T> & operator++(int) { m_pPtr ++; return *this; };
        SmartHeapMemPtr<T> & operator--(int) { m_pPtr --; return *this; };

        // Member operators
        inline T& operator [](const int n)
        {
            if ((DWORD_PTR) (m_pPtr + n) < m_pData->m_pStartMemPtr || (DWORD_PTR) (m_pPtr + n) > m_pData->m_pEndMemPtr + 1 - sizeof(T))  // 越界检查
                throw char("Pointer bounds error!");
            return m_pPtr[n];
        };
        inline const T& operator [](const int n) const
        {
            if ((DWORD_PTR) (m_pPtr + n) < m_pData->m_pStartMemPtr || (DWORD_PTR) (m_pPtr + n) > m_pData->m_pEndMemPtr + 1 - sizeof(T))  // 越界检查
                throw char("Pointer bounds error!");
            return m_pPtr[n];
        };

        // Cast operator
        template<typename t2> operator t2() { return (t2) m_pPtr; };
        template<typename t2> operator t2() const { return (t2) m_pPtr; };

        // Release
        void Release() { if (m_pData) DecRef(); m_pData = 0; m_pPtr = 0; };


        // Decrease reference
        void DecRef()
        {
            m_pData->m_nRefCnt --;
            if (m_pData->m_nRefCnt == 0)
            {
                if (m_pData->m_pStartMemPtr)
                {
                    PPREFIX pPrefix = IsManagedMemory((void*) m_pData->m_pStartMemPtr);
                    if (pPrefix)  // fully managed
                    {
                        pPrefix->d.nRefCnt --;
                        if (pPrefix->d.nRefCnt == 0)
                        {
                            if (pPrefix->d.bIsArray)
                                DEL_ARRAY((T*) m_pData->m_pStartMemPtr)
                            else
                                DEL_PTR((T*) m_pData->m_pStartMemPtr)
                        }
                    }
//                  else
//                      throw char("Deleting unmanaged memeory!");
                }
                delete m_pData;
                m_pData = NULL;
            }
        };

    private:
        // Add reference
        void IncRef()
        {
            m_pData->m_nRefCnt ++;
        };

        // Check if it is fully managed, partially managed or unmanaged. Return a prefix if fully managed
        PPREFIX IsManagedMemory(void *p)
        {
            const static int PREFIX_SIG = ('p' << 24) | ('r' << 16) | ('f' << 8) | 'x';
            __try 
            { 
                // For array elements that have destructors, C++ will allocate 4 bytes more than requested and fill the first 4 bytes with
                // length of array. So, we here need to check if it is such case.
                if (((DWORD_PTR) p) % ALIGNMENT != 0)  // not aligned as expected (this points to offset 4 in the allocated memory)
                    p = (void*) (((DWORD_PTR) p) & ~(ALIGNMENT - 1));
                PPREFIX pPrefix = (PPREFIX) p - 1;
                if (*((int*) pPrefix->d.szToken) == PREFIX_SIG)
                    return pPrefix;
                else
                    return NULL;
            } 
            __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 
                     EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
            { 
                return NULL;
            }
        };

    };

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值