[C++]野指標的產生以及應對辦法

來源:互聯網
上載者:User

很大程度上,野指標都是因為編碼不善,習慣不好所產生的.

要解決野指標,就要養成好習慣,不要動不動就public資料成員,所有的資料訪問都抽象成介面,最好只在一個地方delete資料.

前段時間遊戲技術測試,down機無限,搞的很頭疼.後來用valgrind的memcheck工具,找到很多野指標.

valgrind很好用,除了有一點慢:-)

valgrind --tool=memcheck --leak-check=full --log-file=./log_file.log --showpossibly-lost=no --malloc-fill=0xff --free-fill=0x11 ./execFile

用上面的語句,就可以啟動一個execFile,順便把所有malloc記憶體設定成0xff,free記憶體設定成0x11,還會統計記憶體泄露(在log_file.log內).簡單易用.

然後麼,一個一個去fix....

跟同學交流,他們那邊有一個辦法,去解決這個野指標問題,也是很巧妙的,不敢獨享:-D

A對象會被n個其他對象B引用,就是其他n個對象B會持有指向A的指標.

如果A被delete,其他n個對象B指向A的指標的記憶體已經不可訪問,這個時候訪問那塊記憶體,就會發生未定義行為.

天知道會怎麼樣!!!也許會down掉,也許不會.

他們是搞的:

1) 對象B對A的引用,A自己會儲存一份記錄,標記有對象B引用過自己

2) 對象B析構,會通知A,這個時候,A會去除B對自己的引用的標記

3) A析構,A會把所有指向自己的指標,設定成NULL

這是基本思想.

下面給出簡單的實現,非安全執行緒,有什麼問題可以提出...

#ifndef __REFERABLE_H__#define __REFERABLE_H__#include <vector>#include "ref_ptr.h"template<typename T>class referable{public:        typedef referable** RefAddress;    virtual ~referable()    {        for (container_iter iter = m_references.begin();            iter != m_references.end();            ++iter)        {            **iter = NULL;         }    }private:    typedef typename std::vector<RefAddress> container_type;    typedef typename container_type::iterator container_iter;    friend class ref_ptr<T>;    void on_reg(RefAddress addr)    {        for (container_iter iter = m_references.begin();            iter != m_references.end();            ++iter)        {            if(*iter == addr) return;        }        m_references.push_back(addr);    }    void on_unreg(RefAddress addr)    {        for (container_iter iter = m_references.begin();            iter != m_references.end();)        {            if(*iter == addr)                iter = m_references.erase(iter);            else                ++iter;        }    }private:    container_type m_references;};#endif
#ifndef __REFERENCE_POINTER_H__#define __REFERENCE_POINTER_H__#include "referable.h"template<typename T>class ref_ptr{public:    ref_ptr():m_ptr(NULL){}    ref_ptr(T *ptr):m_ptr(ptr)    {        add_ref();    }    ref_ptr(const ref_ptr<T>& ref):m_ptr(ref.m_ptr)    {        add_ref();    }    virtual ~ref_ptr()    {        remove_ref();    }    ref_ptr<T>& operator = (const ref_ptr<T>& ref)    {        if(this == &ref) return *this;        remove_ref();        m_ptr = ref.m_ptr;        add_ref();        return *this;    }    ref_ptr<T>& operator = (T *ptr)    {        if(m_ptr != ptr)        {            remove_ref();            m_ptr = ptr;            add_ref();        }        return *this;    }public:    T*  operator->() const { return m_ptr; }    T&  operator*() const { return *m_ptr; }    operator T*() const { return m_ptr; }    operator bool() const { return m_ptr; }private:    void add_ref()    {        if(m_ptr) ((referable<T>*)m_ptr)->on_reg((referable<T>**)&m_ptr);    }    void remove_ref()    {        if(m_ptr) ((referable<T>*)m_ptr)->on_unreg((referable<T>**)&m_ptr);        m_ptr = NULL;    }private:    T* m_ptr;};#endif

測試代碼:

class object : public referable<object>{public:    int x;};void test(){    object *a = new object;    object *a1 = new object;    ref_ptr<object> b = a;    a->x = 10;    assert(b && b->x == 10);    delete a;    assert(!b);    b = a1;    assert(b);}

這個東西看上去還不錯.

不過習慣還是很重要滴

PS:

一般引用都是只有四五個,所以vector效能足夠好,我測試過~~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.