zoukankan      html  css  js  c++  java
  • [C++]野指针的产生以及应对办法

    很大程度上,野指针都是因为编码不善,习惯不好所产生的.

    要解决野指针,就要养成好习惯,不要动不动就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性能足够好,我测试过~~

  • 相关阅读:
    元素定位不到的问题,Timeout,nosuch element,unable locate等
    webpack的安装
    Mysql修改表
    Mysq表的创建和l数据类型
    Mysql的库操作
    面向对象的序列化和反序列化
    类的关键字:final、const
    面向对象接口以及和继承的混合案例
    DOM创建移除替换元素
    抽象类
  • 原文地址:https://www.cnblogs.com/egmkang/p/2189548.html
Copyright © 2011-2022 走看看