通过重载 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 nodevoid 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 版权声明:本文为博主原创文章,转载请附上博文链接!