To a large extent, wild pointers are produced by poor coding and habits.
To solve the problem of wild pointers, we must develop a good habit. Public Data members should not be moved, and all data access should be abstracted as interfaces. It is best to delete data only in one place.
Some time ago, there was no limit to the game technology test, which caused a headache. Later, we used valgrind's memcheck tool to find many wild pointers.
Valgrind is very useful, except for a little slow :-)
Valgrind -- tool = memcheck -- leak-check = full -- log-file =. /log_file.log -- showpossibly-lost = No -- malloc-fill = 0xff -- free-fill = 0x11. /execfile
With the preceding statement, you can start an execfile, set all malloc memory to 0xff, free memory to 0x11, and count Memory leakage (in log_file.log ). easy to use.
Then, fix them one by one ....
To communicate with colleagues, there is a solution on the other side to solve this wild pointer problem, which is also very clever and does not dare to exclusive:-d
Object A will be referenced by N other objects B, that is, the other n objects B will hold a pointer to.
If a is deleted, the memory of the pointer to a of the other n objects B is no longer accessible. In this case, the access to the memory will lead to undefined behavior.
God knows what will happen !!! May be down, maybe not.
They are engaged in:
1) When object B references a, a saves a record and marks that object B has referenced itself.
2) object B's structure will notify a. At this time, a will remove B's reference mark
3) A destructor. A sets all the pointers pointing to itself to null.
This is the basic idea.
The following provides a simple implementation, non-thread security. If you have any questions, you can raise them...
# 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
TestCode:
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 );}
This looks good.
However, habits are very important.
PS:
Generally, there are only four or five references, so the vector performance is good enough. I have tested it ~~