C++對象對new,delete攔截實現內存監視

object_memory_monitoring - 源碼文件 - 點擊下載

C或C語言和其他語言不同,需要自己管理內存,對不需要的內存要及時釋放,否則就會導致內存泄露,導致內存不足讓程序崩潰。
在C程序員中,很容易導致內存忘記釋放,特別是在程序出現異常的情況下。
在對象中我們可以對new,delete進行重寫,實現內存監視

#include <iostream>
#include <stdlib.h>

using namespace std;

class man
{
public:
    //計數器
    static int jishuqi;
    //用於指向頭結點
    static man * head;
    //用於指向當前節點
    static man * local;
    man * next;
    man()
    {
        //cout << "man preject init!" << endl;
    }
    ~man()
    {
        //cout << "man preject end!" << endl;
    }
    static void * operator new(size_t size)
    {
        man *ptemp = ::new man;
        ptemp->next = NULL;
        if(head == NULL){
            head = ptemp;
        }
        if(local == NULL){
            local = ptemp;
        }
        else{
            local->next = ptemp;
            local = ptemp;
        }
        jishuqi += 1;
        cout << "man preject building! jishuqi = " << jishuqi << " address = " << ptemp << endl;
        return ptemp;
    }
    static void operator delete(void *p)
    {
        //用於指向當前節點
        man * a = head;
        //用於指向當前節點的上一個節點
        man * b = head;
        //在內存鏈表中查找將要刪除的地址
        while(a != NULL){
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
            //查找到地址
            if( a == p ){
                //如果將要刪除的地址在內存鏈表中是頭結點
                if(a == head ){
                    //如果鏈表中只有一個結點,即頭結點,就重新初始化鏈表
                    if( a->next == NULL ){
                        head = NULL;
                        local = NULL;
                    }
                    //如果鏈表有多個個結點,將頭結點的next指向第二個結點
                    else{
                        head = a->next;
                    }
                }
                //如果將要刪除的地址在內存鏈表中是尾結點,就將尾結點的上一個節點指向NULL,將local指針指向尾結點的上一個節點
                else if( a->next == NULL){
                    b->next = NULL;
                    local = b;
                }
                //如果將要刪除的地址在內存鏈表中是中間節點,就被刪除節點的next指針 賦值給 將被刪除節點的上一個節點的next指針
                else{
                    b->next = a->next;
                }
                break;
            }
            b = a;
            //指針後移
            a = a->next;
        }
        jishuqi -= 1;
        cout << "man preject delete! jishuqi = " << jishuqi << " address = " << p << endl;
        ::delete p;
    }
    //清除所有類
    static void clean()
    {
        man * a = head;
        man * b = NULL;
        while(a != NULL){
            cout << "a = " << a << endl;
             b = a->next;
             delete a;
             a = b;
        }
    }
};

int man::jishuqi = 0;
man * man::head = NULL;
man * man::local = NULL;


void test(){
    man * wnh1 = new man;
    man * wnh2 = new man;
    man * wnh3 = new man;
    man * wnh5 = new man;
    man * wnh6 = new man;
    man * wnh7 = new man;
    man * wnh8 = new man;
    system("pause");
    cout << "測試刪除頭指針指向的對象 " << endl;
    delete wnh1;
    system("pause");
    man * a = wnh2->head;
    while(a != NULL){
        cout << "a = " << a << endl;
        a = a->next;
    }
    system("pause");

    cout << "測試刪除中間指針指向的對象 " << endl;
    delete wnh5;
    system("pause");
    a = wnh2->head;
    while(a != NULL){
        cout << "a = " << a << endl;
        a = a->next;
    }
    system("pause");

    cout << "測試刪除最後指針指向的對象 " << endl;
    delete wnh8;
    system("pause");
    a = wnh2->head;
    while(a != NULL){
        cout << "a = " << a << endl;
        a = a->next;
    }
    system("pause");

    cout << "測試刪除最後指針指向的對象重新創建對象時,local指針指向是否正常 " << endl;
    man * wnh9 = new man;
    system("pause");
    a = wnh2->head;
    while(a != NULL){
        cout << "a = " << a << endl;
        a = a->next;
    }
    system("pause");

    cout << "測試刪除全部對象後,head和local指針指向是否正常 " << endl;

    man::clean();
    //delete wnh2;
    //delete wnh3;
    //delete wnh6;
    //delete wnh7;
    //delete wnh9;
    system("pause");
    man * wnh10 = new man;
    system("pause");
    a = wnh2->head;
    while(a != NULL){
        cout << "a = " << a << endl;
        a = a->next;
    }
    system("pause");
}

int main()
{
    test();
    system("pause");
    return 0;
}

結果

man preject building! jishuqi = 1 address = 001978D0
man preject building! jishuqi = 2 address = 00197900
man preject building! jishuqi = 3 address = 00197930
man preject building! jishuqi = 4 address = 00197990
man preject building! jishuqi = 5 address = 001979C0
man preject building! jishuqi = 6 address = 001979F0
man preject building! jishuqi = 7 address = 00197A20
請按任意鍵繼續. . .
測試刪除頭指針指向的對象
a = 001978D0
b = 001978D0
man preject delete! jishuqi = 6 address = 001978D0
請按任意鍵繼續. . .
a = 00197900
a = 00197930
a = 00197990
a = 001979C0
a = 001979F0
a = 00197A20
請按任意鍵繼續. . .
測試刪除中間指針指向的對象
a = 00197900
b = 00197900
a = 00197930
b = 00197900
a = 00197990
b = 00197930
man preject delete! jishuqi = 5 address = 00197990
請按任意鍵繼續. . .
a = 00197900
a = 00197930
a = 001979C0
a = 001979F0
a = 00197A20
請按任意鍵繼續. . .
測試刪除最後指針指向的對象
a = 00197900
b = 00197900
a = 00197930
b = 00197900
a = 001979C0
b = 00197930
a = 001979F0
b = 001979C0
a = 00197A20
b = 001979F0
man preject delete! jishuqi = 4 address = 00197A20
請按任意鍵繼續. . .
a = 00197900
a = 00197930
a = 001979C0
a = 001979F0
請按任意鍵繼續. . .
測試刪除最後指針指向的對象重新創建對象時,local指針指向是否正常
man preject building! jishuqi = 5 address = 00197A20
請按任意鍵繼續. . .
a = 00197900
a = 00197930
a = 001979C0
a = 001979F0
a = 00197A20
請按任意鍵繼續. . .
測試刪除全部對象後,head和local指針指向是否正常
a = 00197900
a = 00197900
b = 00197900
man preject delete! jishuqi = 4 address = 00197900
a = 00197930
a = 00197930
b = 00197930
man preject delete! jishuqi = 3 address = 00197930
a = 001979C0
a = 001979C0
b = 001979C0
man preject delete! jishuqi = 2 address = 001979C0
a = 001979F0
a = 001979F0
b = 001979F0
man preject delete! jishuqi = 1 address = 001979F0
a = 00197A20
a = 00197A20
b = 00197A20
man preject delete! jishuqi = 0 address = 00197A20
請按任意鍵繼續. . .
man preject building! jishuqi = 1 address = 00197A20
請按任意鍵繼續. . .
a = 00197A20

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章