Weak pointer的实现方法.
1#include <assert.h>
2#include <map>
3#include <stdio.h>
4
5// memory leak checker
6struct Value
7{
8 bool valid;
9 int line;
10
11 Value()
12 :valid(false), line(-1)
13 {}
14
15 Value(bool v, int l)
16 :valid(v), line(l)
17 {
18 }
19};
20
21typedef std::map<void*, Value> ContainerType;
22ContainerType myMap;
23
24#define mynew(x) mynew_(x, __LINE__)
25
26void checkMemory()
27{
28 size_t n = myMap.size();
29 //assert(n==0);
30
31 if(n>0)
32 {
33 printf("Memory leak found:\n");
34 for (ContainerType::const_iterator it=myMap.begin();
35 it!=myMap.end();++it)
36 {
37 printf("Line %d\n", it->second.line);
38 }
39 assert(0);
40 }
41}
42
43template <class T>
44T* mynew_(T const &n, int line)
45{
46 T* p = (T*)malloc(sizeof(T));
47 *p = n;
48 myMap[p]=Value(true, line);
49 return p;
50}
51
52void mydelete(void* p)
53{
54 ContainerType::iterator it = myMap.find(p);
55 assert(it!=myMap.end());
56 myMap.erase(it);
57 free(p);
58}
59
60class AutoPtr
61{
62public:
63 explicit AutoPtr(int *p=0)
64 :p_(p), refCnt_(mynew(int(1))), valid_(mynew(bool(p?true:false)))
65 {}
66
67 ~AutoPtr()
68 {
69 if(p_)
70 {
71 mydelete (p_);
72 }
73
74 (*refCnt_)--;
75
76 *valid_ = false;
77
78 assert(*refCnt_>=0);
79 if(*refCnt_==0)
80 {
81 mydelete(refCnt_);
82 mydelete(valid_);
83 }
84 }
85
86 bool empty() const
87 {
88 if(!*valid_)
89 assert(p_==0);
90 else
91 assert(p_!=0);
92
93 return !(*valid_);
94 }
95private:
96 friend class WeakPtr;
97 AutoPtr(const AutoPtr&);
98 AutoPtr& operator =(const AutoPtr&);
99
100 int *p_;
101 bool *valid_;
102 int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
103};
104
105class WeakPtr
106{
107public:
108 // ctor
109 WeakPtr()
110 :p_(0), refCnt_(mynew(int(1))), valid_(mynew(bool(false)))
111 {
112 }
113
114 explicit WeakPtr(AutoPtr& p) //p must be valid
115 :p_(&p), refCnt_(p.refCnt_),valid_(p.valid_)
116 {
117 (*p_->refCnt_)++;
118 }
119
120 WeakPtr(const WeakPtr& rhs) //p must be valid
121 {
122 construct(rhs);
123 }
124
125 ~WeakPtr()
126 {
127 destroy();
128 }
129
130 // get
131 bool empty() const
132 {
133 assert((*refCnt_)>=0);
134 return !(*valid_);
135 }
136
137 // operator
138 WeakPtr& operator=(const WeakPtr &rhs)
139 {
140 if(this!=&rhs)
141 {
142 destroy();
143 construct(rhs);
144 }
145 return *this;
146 }
147
148private:
149 void destroy()
150 {
151 (*refCnt_)--;
152
153 assert((*refCnt_)>=0);
154 if(0==*refCnt_)
155 {
156 mydelete(refCnt_);
157 mydelete(valid_);
158 }
159
160 }
161 void construct(const WeakPtr &rhs)
162 {
163 p_ = rhs.p_;
164 refCnt_ = rhs.refCnt_;
165 valid_ = rhs.valid_;
166 (*refCnt_)++;
167 }
168
169 AutoPtr *p_;
170 bool *valid_;
171 int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
172};
173
174void Test()
175{
176 WeakPtr p1;
177
178 assert(p1.empty());
179 {
180 AutoPtr p(mynew(int(100)));
181 p1 = WeakPtr(p);
182 assert(!p1.empty());
183 assert(!p.empty());
184 }
185 assert(p1.empty());
186
187 //mynew(int());
188}
189
190void main()
191{
192 Test();
193 checkMemory();
194}
2#include <map>
3#include <stdio.h>
4
5// memory leak checker
6struct Value
7{
8 bool valid;
9 int line;
10
11 Value()
12 :valid(false), line(-1)
13 {}
14
15 Value(bool v, int l)
16 :valid(v), line(l)
17 {
18 }
19};
20
21typedef std::map<void*, Value> ContainerType;
22ContainerType myMap;
23
24#define mynew(x) mynew_(x, __LINE__)
25
26void checkMemory()
27{
28 size_t n = myMap.size();
29 //assert(n==0);
30
31 if(n>0)
32 {
33 printf("Memory leak found:\n");
34 for (ContainerType::const_iterator it=myMap.begin();
35 it!=myMap.end();++it)
36 {
37 printf("Line %d\n", it->second.line);
38 }
39 assert(0);
40 }
41}
42
43template <class T>
44T* mynew_(T const &n, int line)
45{
46 T* p = (T*)malloc(sizeof(T));
47 *p = n;
48 myMap[p]=Value(true, line);
49 return p;
50}
51
52void mydelete(void* p)
53{
54 ContainerType::iterator it = myMap.find(p);
55 assert(it!=myMap.end());
56 myMap.erase(it);
57 free(p);
58}
59
60class AutoPtr
61{
62public:
63 explicit AutoPtr(int *p=0)
64 :p_(p), refCnt_(mynew(int(1))), valid_(mynew(bool(p?true:false)))
65 {}
66
67 ~AutoPtr()
68 {
69 if(p_)
70 {
71 mydelete (p_);
72 }
73
74 (*refCnt_)--;
75
76 *valid_ = false;
77
78 assert(*refCnt_>=0);
79 if(*refCnt_==0)
80 {
81 mydelete(refCnt_);
82 mydelete(valid_);
83 }
84 }
85
86 bool empty() const
87 {
88 if(!*valid_)
89 assert(p_==0);
90 else
91 assert(p_!=0);
92
93 return !(*valid_);
94 }
95private:
96 friend class WeakPtr;
97 AutoPtr(const AutoPtr&);
98 AutoPtr& operator =(const AutoPtr&);
99
100 int *p_;
101 bool *valid_;
102 int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
103};
104
105class WeakPtr
106{
107public:
108 // ctor
109 WeakPtr()
110 :p_(0), refCnt_(mynew(int(1))), valid_(mynew(bool(false)))
111 {
112 }
113
114 explicit WeakPtr(AutoPtr& p) //p must be valid
115 :p_(&p), refCnt_(p.refCnt_),valid_(p.valid_)
116 {
117 (*p_->refCnt_)++;
118 }
119
120 WeakPtr(const WeakPtr& rhs) //p must be valid
121 {
122 construct(rhs);
123 }
124
125 ~WeakPtr()
126 {
127 destroy();
128 }
129
130 // get
131 bool empty() const
132 {
133 assert((*refCnt_)>=0);
134 return !(*valid_);
135 }
136
137 // operator
138 WeakPtr& operator=(const WeakPtr &rhs)
139 {
140 if(this!=&rhs)
141 {
142 destroy();
143 construct(rhs);
144 }
145 return *this;
146 }
147
148private:
149 void destroy()
150 {
151 (*refCnt_)--;
152
153 assert((*refCnt_)>=0);
154 if(0==*refCnt_)
155 {
156 mydelete(refCnt_);
157 mydelete(valid_);
158 }
159
160 }
161 void construct(const WeakPtr &rhs)
162 {
163 p_ = rhs.p_;
164 refCnt_ = rhs.refCnt_;
165 valid_ = rhs.valid_;
166 (*refCnt_)++;
167 }
168
169 AutoPtr *p_;
170 bool *valid_;
171 int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
172};
173
174void Test()
175{
176 WeakPtr p1;
177
178 assert(p1.empty());
179 {
180 AutoPtr p(mynew(int(100)));
181 p1 = WeakPtr(p);
182 assert(!p1.empty());
183 assert(!p.empty());
184 }
185 assert(p1.empty());
186
187 //mynew(int());
188}
189
190void main()
191{
192 Test();
193 checkMemory();
194}
- 上一篇 Linux安装与启动
- 下一篇 一个数据包经过路由器和交换机各会发生什么变化.