new編

4830 ワード

c++では、私たちはnewに慣れていて、ダイナミックオブジェクトを生成するとnewを呼び出しますが、皆さんは本当にその下層の動作方法を知っていますか?new操作はnewオペレータを呼び出すことによってメモリを割り当てるものであり、mallocの役割と同様に、new placementを呼び出すオペレータだけでこの割り当てられたメモリ上でクラスの構造関数を呼び出し、オブジェクトへのポインタを返す.このコードを見てみましょう
#ifndef BASE_H
#define BASE_H
#include 
using namespace std;
class Base
{
      public:
        Base()
        {
            std::cout << "call the Base:Base" << std::endl;
        }
};
#endif

//    operator new    
extern void* func (size_t size);

//base.cpp
#include "base.h"
#include 
#include 
void* func(size_t size)
{
    if(!size)
    {
        return NULL;
    }
    return malloc(size);
}

int main()
{
    bool ret = false;
    do
    {
        //    
        void *ptr = func(sizeof(Base));
        if(!ptr)
        {
          break;
        }
        //      new placement, ptr        Base  
        Base *base = new(ptr)(Base);
        if(!base)
        {
              break;
         }
        ret = true;
        delete base;
        base = NULL;
    }while(false);
    return ret ? 0 : 1;
}

上のコードを通じて、私达は全体のnewオペレータの全体の底层の呼び出しの流れを理解することができて、私达はoperator new関数を再载することができて、自分でメモリを割り当てる目的を达成することができて、他にもいくつかの妙用があって、例えばメモリの分配と回収の情况を追って、システムがメモリの漏洩が発生するかどうかを见て、これらの技巧、次回更に补います!
では、operator newとoperator deleteを再ロードしてメモリの漏洩状況を追跡します.まずコードを見て
//func.h
#ifndef FUNC_H
#define FUNC_H

#define DEBUG

#ifdef DEBUG
void *operator new (size_t size,const char *file,size_t line);
void operator delete (void *ptr);
#define Debug_New new(__FILE__,__LINE__)
#else
#define Debug_New new
#endif

#endif

//func.cpp
#include "func.h"
#include 
#include 

#ifdef DEBUG
//     
const int FILE_SIZE = 32;
typedef struct Node
{
      char file[FILE_SIZE];
      size_t line;
      size_t size;
      Node *next;
}Node;
//Node*     
const int NODE_lEN = 1024;
//          
static Node* nodeArray[NODE_LEN];
//hash p       
int hashIndex(void *p)
{
      unsigned long val = reinterpret_cast(p);
      return val % NODE_lEN;
}
//     Node
bool insert(Node *pn,void *p)
{
    ret = false;
    do
    {
        if(!pn || !p)
        {
            break;
        }
        int hashVal = hashIndex(p);
        pn->next = nodeArray[hashVal];
        nodeArray[hashVal] = pn;
        pn->next = pre;
        ret = true;
    }while(false);
    printf("[    ](%s,   :%s,  :%d,  :%d)
",(ret ? " " :" "),pn->file,pn->line,pn->size); return ret; } // Node Node* erase(void *p) { Node *ret = NULL; do { int hashVal = hashIndex(p); Node *pre = nodeArray[hashVal]; if((void*)pre== (p - sizeof(Node)) { ret = pre; nodeArray[hashVal] = pre->next; } else { Node *node = pre->next; while(node) { if(void*)node == (p - sizeof(Node)) { ret = node; pre->next = node->next; break; } pre = node; node = pre->next; } } }while(false); if(ret) { printf("[ ](%s, :%s, :%d, :%d)
",(true ? " " : " "),ret->file,ret->line,ret->size); } else { printf("[ ]( )
"); } return ret; } // new void* operator new (size_t size,const char *file,size_t line) { void *ret = NULL; bool flg = false; do { if(!size) { break; } int total = sizeof(Node) + size; void *pv = std::malloc(total); Node *pn = (Node*)(pv); if(!pn) { break; } strncpy(pn->file,file,sizeof(pn->file)-1); pn->line = line; pb->size = size; pn->next = NULL; ret = insert(pn,(char*)pv + sizeof(Node)) ? (char*)pv + sizeof(Node) : NULL; }while(false); return ret; } // delete void operator delete (void* p) { void *ret = (void*)erase(p); free(ret); } //base.h #ifndef BASE_H #define BASE_H class Base { }; #endif //main.cpp #include "base.h" #include "func.h" int main() { Base *ptr = new Base(); delete ptr; ptr = NULL; return 0; }

グローバルなoperator newとグローバルなoperator delete関数を再ロードし、ノードのキューを通じてメモリを制御し、ログを通じて、どのメモリが解放されていないかを明らかにすることができます.gitに入れました住所は:https://github.com/flyerSon/practice/tree/master/leak