C++ 重载 new 和 delete

https://blog.csdn.net/zhaoyongCNSX/article/details/80640207
概述
通过重载 new 和 delete, 从而控制内存分配的过程.
执行 new 的过程: 
编译器调用名为operator new(或operator new[])的标准库函数, 非配一块足够大, 原始, 未命名的内存空间.
编译器运行相应构造函数, 并未其传入初始值.
返回一个指向该对象的指针.
执行 delete 的过程: 
先执行相应的析构函数.
编译器调用名为operator delete(或operator delete[])的标准库函数释放内存空间.
编译器查找 new 和 delete 的顺序: 
若操作对象是类类型, 则编译器首先在类或基类的作用域中查找. 若类中含 operator new (或 operator delete) 成员, 则调用这些成员.
编译器在全局作用域中查找匹配的函数, 若有自定义版本, 则使用.
若没找到, 则使用标准库定义的版本.
可以使用::(作用域运算符)忽略定义在类中的 new 或 delete 函数. eg: ::new只在全局作用域中查找.
new 和 new[]. 使用以下示例说明: 
new int 编译器解释为 new(sizeof(int)).
new int[10] 编译器解释为 new(sizeof(int) * 10).
new 和 operator new 函数的区别 (delete 和 operator delete 类似): 
new 除了调用 operator new 函数, 还要调用构造函数.
我们平常说的重载 new, 其实只是重载 operator new 函数. 我们无法阻止之后调用构造函数的行为(也没必要阻止).
重载
我们可以在类中, 或是在全局作用域中定义自己版本的 operator new 和 operator delete.
当在类中定义 operator new 和 operator delete 时, 他们是隐式静态 的(也就是说, 无需显式声明 static, 不过最好还是声明吧, 保持统一性). 为什么是静态的呢? 因为 operator new 用于对象构造前, operator delete 用于析构后. 而且既然是静态的, 也就无法操作类的非静态数据成员了.
operator new 和 operator delete
可定义其他类型的 operator new.
void *operator new(size_t, void*); 该形式只供标准库使用, 不允许被用户重载.
void *operator new(size_t size) {
    if (void *mem = malloc(size)) {
        return mem;
    } else {
        throw bad_alloc();
    }
}

void operator delete(void mem) noexcept {
    free(mem);
}
1
2
3
4
5
6
7
8
9
10
11
内存泄漏检测
资料
http://www.cnblogs.com/pangxiaodong/archive/2011/08/29/2158136.html
实现
MemInfoNode 用于记录申请的一块内存的信息. MemList 为一个单项链表, 存储每个申请的内存块的数据.
#define new new(__FILE__, __LINE__) 的作用是, 可以在代码中直接方便的使用 new, 不改变原来代码中的语法. eg: new int将替换为new(__FILE__, __LINE__) int. 编译器最后将调用 operator new(sizeof(int), __FILE__, __LINE__)函数.
在 MemList 中要使用 malloc 和 free. 防止使用 new, delete 造成的递归死循环.
#include <iostream>
using namespace std;

class MemInfoNode {
private:
    void *pMem = NULL;    //memory address
    size_t memSize = 0;   
    const char *codeFile = NULL;
    unsigned int codeLine = 0;
    MemInfoNode *pNext = NULL;    //point to next node

    void Print(ostream &out = std::cout) {
        out << " FileName: " << codeFile
            << " LineNum: " << codeLine
            << " MemAddr: " << pMem
            << " MemSize: " << memSize
            << std::endl;
    }

    friend class MemList;
};

class MemList {
public:
    MemList() {}
    ~MemList() {
        MemInfoNode *nTmp = NULL;
        //释放泄露内存
        while (m_pHeadNode) {
            if (m_pHeadNode->pMem) { 
                free(m_pHeadNode->pMem); 
            }
            // move to next node
            nTmp = m_pHeadNode->pNext;
            free(m_pHeadNode);
            m_pHeadNode = nTmp->pNext;
        }
    }

    bool Prepend(void *pMem, size_t memSize, const char *fileName, unsigned int lineNo) {
        if (!pMem) {
            return false;
        }
        MemInfoNode *pNode = (MemInfoNode*)malloc(sizeof(MemInfoNode));
        pNode->pMem = pMem; pNode->memSize = memSize; pNode->codeFile = fileName; pNode->codeLine = lineNo;
        pNode->pNext = m_pHeadNode; m_pHeadNode = pNode;
        return true;
    }

    bool Remove(void *ptr) {
        if (!ptr) {
            return false;
        }

        MemInfoNode *n_pIt = m_pHeadNode;
        MemInfoNode *n_pPtr = NULL;
        while (n_pIt) {
            if (n_pIt->pMem == ptr) {    //findIt
                // 从 list 中 remove node
                if (!n_pPtr) {
                    m_pHeadNode = n_pIt->pNext;
                }
                else {
                    n_pPtr->pNext = n_pIt->pNext;
                }

                // free node
                free(n_pIt);
                return true;
            }
            n_pPtr = n_pIt;
            n_pIt = n_pIt->pNext;
        }
        return false;
    }

    friend ostream & operator << (ostream &out, MemList obj);

    void Result(ostream &out = std::cout) {
        if (!m_pHeadNode) {
            out << "[OK] This Application no memory leak!" << std::endl;
        }
        else {
            out << "[ERR] This Application have memory leak!" << std::endl;
            MemInfoNode *n_pIt = m_pHeadNode;
            while (n_pIt) {
                n_pIt->Print(out);
                n_pIt = n_pIt->pNext;
            }
        }
    }

private:
    MemInfoNode *m_pHeadNode = NULL;
};

ostream & operator << (ostream &out, MemList obj) {
    obj.Result(out);
    return out;
}

/*---------------  全局变量 ------------------*/
MemList mem_list; 

/*-------------- 重载 new new[] delete delete[] ---------------*/
void *operator new(size_t size, const char *fileName, unsigned int lineNo){
    void *pMem = malloc(size);
    if (pMem) {
        mem_list.Prepend(pMem, size, fileName, lineNo);
    }
    return pMem;
}
void *operator new[](size_t size, const char *fileName, unsigned int lineNo){
    return operator new(size, fileName, lineNo);    //Tips: 不能用 new, 而应该用 operator new
}

void operator delete(void *pMem) {
    if (pMem) {
        free(pMem);
        mem_list.Remove(pMem);
    }
}
void operator delete[](void *pMem) {
    operator delete(pMem);
}


/*------------------ 将 new 替换为重载的 new ----------------*/
#define new new(__FILE__, __LINE__)


void Test_bad_code() {
    int *p1 = new int;
    int *p2 = new int;
    int *p3 = new int[10];
    int *p4 = new int[20];

    delete p1;
    delete []p3;
}
void Test_good_code() {
    int *p1 = new int;
    int *p2 = new int;
    int *p3 = new int[10];
    int *p4 = new int[20];

    delete p1;
    delete p2;
    delete []p3;
    delete []p4;
}


int main()
{
    Test_good_code();
    Test_bad_code();

    //cout << mem_list;
    mem_list.Result();

    int tmp;
    cin >> tmp;
    return 1;
}
--------------------- 
作者:zhaoyongCNSX 
来源:CSDN 
原文:https://blog.csdn.net/zhaoyongCNSX/article/details/80640207 
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://my.oschina.net/u/4000302/blog/3083562

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值