zoukankan      html  css  js  c++  java
  • c++ [wrong]simple "Garbage Collector"

    In fact, Ptr alone can accomplish the task mentioned below.

    Implementation see Ptr.h, main2.cpp. In C++11, we also have a better choice: std::shared_ptr (as you can see in main3.cpp).

    main2.cpp

     1 #include "Ptr.h"
     2 
     3 #include <iostream>
     4 
     5 using namespace std;
     6 
     7 class Box
     8 {
     9     public:
    10         void dosomething() { cout << "Box dosomething" << endl; }
    11         Box() { cout << "Box cons" << endl; }
    12         ~Box() { cout << "Box des" << endl; }
    13 };
    14 
    15 Ptr<Box> global;
    16 
    17 
    18 Ptr<Box> func() {
    19     Ptr<Box> pb(new Box());
    20     return pb;
    21 }
    22 
    23 void call(Ptr<Box> ptr)
    24 {
    25     if(ptr)
    26         ptr->dosomething();
    27     else
    28         cout << "ptr is null" << endl;
    29 }
    30 
    31 
    32 
    33 int main()
    34 {
    35     Ptr<Box> p = func();
    36     p->dosomething();
    37     (*p).dosomething();
    38     Ptr<Box> p2 = p;
    39     call(p2);
    40     p2.reset();
    41     cout << "after p2.reset" << endl;
    42     global = p;
    43     p.reset();
    44     call(p);
    45     (*global).dosomething();
    46     global.reset();
    47     cout << "after global.reset" << endl;
    48     return 0;
    49 }

    Ptr.h

     1 #ifndef PTR_H
     2 #define PTR_H
     3 
     4 #include <cstddef>
     5 
     6 template <typename TYPE>
     7 class Ptr {
     8 
     9     public:
    10         void reset()
    11         {
    12             dec_use();
    13         }
    14         Ptr& operator=(const Ptr<TYPE> &copy)
    15         {
    16             dec_use();
    17             obj = copy.obj;
    18             use_count = copy.use_count;
    19             if (use_count) ++*use_count;
    20             return *this;
    21         }
    22         TYPE* operator->() { return obj; }
    23         TYPE& operator*() { return *obj; }
    24         const TYPE* operator->() const { return obj; }
    25         const TYPE& operator*() const { return *obj; }
    26         operator bool() const { return (obj != NULL); }
    27 
    28         Ptr(): obj(NULL), use_count(NULL) {}
    29         Ptr(TYPE *obj_): obj(obj_), use_count(new int(1)) {}
    30         Ptr(const Ptr &copy): obj(NULL), use_count(NULL)
    31         {
    32             obj = copy.obj;
    33             use_count = copy.use_count;
    34             if (use_count) ++*use_count;
    35         }
    36         ~Ptr()
    37         {
    38             dec_use();
    39         }
    40     private:
    41         void dec_use() // decrease use_count
    42         {
    43             if (use_count != NULL) {
    44                 if( --*use_count == 0) {
    45                     delete obj;
    46                     delete use_count;
    47                 }
    48                 obj = NULL;
    49                 use_count = NULL;
    50             }
    51         }
    52         TYPE *obj; // the actual object
    53         int *use_count; // number of Ptr objects point to 'obj'
    54 };
    55 
    56 #endif // PTR_H

    main3.cpp

     1 #include <memory>
     2 
     3 #include <iostream>
     4 
     5 using namespace std;
     6 
     7 class Box
     8 {
     9     public:
    10         void dosomething() { cout << "Box dosomething" << endl; }
    11         Box() { cout << "Box cons" << endl; }
    12         ~Box() { cout << "Box des" << endl; }
    13 };
    14 
    15 shared_ptr<Box> global;
    16 
    17 
    18 shared_ptr<Box> func() {
    19     shared_ptr<Box> pb(new Box());
    20     return pb;
    21 }
    22 
    23 void call(shared_ptr<Box> ptr)
    24 {
    25     if(ptr)
    26         ptr->dosomething();
    27     else
    28         cout << "ptr is null" << endl;
    29 }
    30 
    31 
    32 
    33 int main()
    34 {
    35     shared_ptr<Box> p = func();
    36     p->dosomething();
    37     (*p).dosomething();
    38     shared_ptr<Box> p2 = p;
    39     call(p2);
    40     p2.reset();
    41     cout << "after p2.reset" << endl;
    42     global = p;
    43     p.reset();
    44     call(p);
    45     (*global).dosomething();
    46     global.reset();
    47     cout << "after global.reset" << endl;
    48     return 0;
    49 }

    ---------------------------------------- stupidest iead I've ever seen -----------------------------------------

    |                                                                                                                                                         |

    |                                                                                                                                                         |

    The idea is to create a Ptr type that acts like a reference in Java.

    And A Garbage Collector (MemMgr) type that acts like a garbage collector in Java.

    Just a toy. :D

    Question: why not delete all memory fragments managed by MemMgr in its destructor?

    Answer: If you want to delete a piece of memory, you must cast the void* pointer to the exact type of that memory. However, there's no way for a MemMgr to know the type of the memory pieces, because type information is not managed by MemMgr. And you can't use the free function from <cstdlib>. For example, if you write "MemMgr *p = new MemMgr; free(p);" you'll find that the destructor of MemMgr is not called. And As shown in "test.cpp". "free" only works in pair with "malloc" or "realloc" etc functions in <cstdlib>. "delete" should work in pair with "new". 

    see this question: http://stackoverflow.com/questions/1518711/how-does-free-know-how-much-to-free

    test.cpp

    1 #include "MemMgr.h"
    2 #include <cstdlib>
    3 
    4 int main()
    5 {
    6     MemMgr *p = new MemMgr;
    7     free(p);
    8     return 0;
    9 }

    main.cpp

     1 #include "MemMgr.h"
     2 
     3 #include <iostream>
     4 
     5 using namespace std;
     6 
     7 class Box
     8 {
     9     public:
    10         void dosomething() { cout << "Box dosomething" << endl; }
    11         Box() { cout << "Box cons" << endl; }
    12         ~Box() { cout << "Box des" << endl; }
    13 };
    14 
    15 Ptr<Box> global;
    16 MemMgr mgr;
    17 
    18 
    19 Ptr<Box> func() {
    20     Ptr<Box> pb = mgr.regist(new Box());
    21     return pb;
    22 }
    23 
    24 
    25 
    26 int main()
    27 {
    28     Ptr<Box> p = func();
    29     p->dosomething();
    30     (*p).dosomething();
    31     Ptr<Box> p2 = p;
    32     p2->dosomething();
    33     cout << "end of main" << endl;
    34     global = p2;
    35     return 0;
    36 }

    MemMgr.h

      1 #ifndef MEMMGR_H
      2 #define MEMMGR_H
      3 
      4 #include <map>
      5 
      6 template <typename TYPE>
      7 class Ptr;
      8 
      9 /**
     10     MemMgr take the idea of Garbage Collector
     11     from the Java language. It's just much simple
     12     and limited.
     13 */
     14 class MemMgr
     15 {
     16     template <typename T> friend class Ptr;
     17     private:
     18         typedef unsigned long count;
     19         template <typename T> void login(T* ptr_obj);
     20         template <typename T> void logout(T* ptr_obj);
     21         std::map<void*, count> cmap;
     22     public:
     23         MemMgr();
     24         /**
     25             Client is responsible to ensure obj is in the heap,
     26             and make sure only use Ptr objects rather than ordinary
     27             pointers when manipulating objects managed by MemMgr.
     28 
     29             Otherwise the behavior of the MemMgr is undefined.
     30 
     31             If MemMgr is destroyed before any Ptr object managed
     32             by it, all Ptr objects managed by that MemMgr are corrupted
     33             and their behavior is undefined, which eventually leads to
     34             memory leak.
     35 
     36             So it's crucial to make sure MemMgr is not destroyed
     37             before ALL Ptr objects managed by it are destroyed.
     38         */
     39         template <typename T> Ptr<T> regist(T *obj);
     40         ~MemMgr();
     41 
     42 };
     43 
     44 /**
     45     Ptr acts like a reference in java.
     46 */
     47 template <typename TYPE>
     48 class Ptr {
     49 
     50     friend class MemMgr;
     51 
     52     public:
     53         Ptr& operator=(const Ptr<TYPE> &copy)
     54         {
     55             if(copy) {
     56                 logout();
     57                 obj = copy.obj;
     58                 mgr = copy.mgr;
     59                 copy.mgr->login(&obj);
     60             } // else leaves obj and mgr NULL
     61             return *this;
     62         }
     63         TYPE* operator->() { return obj; }
     64         TYPE& operator*() { return *obj; }
     65         const TYPE* operator->() const { return obj; }
     66         const TYPE& operator*() const { return *obj; }
     67         operator bool() const { return ( (obj != NULL) && (mgr != NULL) ); }
     68 
     69         Ptr(): obj(NULL), mgr(NULL) {}
     70         Ptr(const Ptr &copy): obj(NULL), mgr(NULL)
     71         {
     72             if(copy) {
     73                 obj = copy.obj;
     74                 mgr = copy.mgr;
     75                 copy.mgr->login(obj);
     76             }
     77         }
     78         ~Ptr()
     79         {
     80             logout();
     81         }
     82     private:
     83         Ptr(TYPE *_obj, MemMgr *_mgr): obj(_obj), mgr(_mgr)
     84         {
     85             mgr->login(obj);
     86         }
     87         void logout() {
     88             if (*this) {
     89                 mgr->logout(obj); obj = NULL; mgr = NULL;
     90             }
     91         }
     92         TYPE *obj;
     93         MemMgr *mgr;
     94 };
     95 
     96 
     97 template <typename T> Ptr<T> MemMgr::regist(T *obj)
     98 {
     99     return Ptr<T>(obj, this);
    100 }
    101 
    102 template <typename T>
    103 void MemMgr::login(T* ptr_obj)
    104 {
    105     std::map<void*, count>::iterator iter = cmap.find(ptr_obj);
    106     if (iter != cmap.end()) {
    107         ++(iter->second);
    108     } else {
    109         cmap.insert(std::pair<void*, count>(ptr_obj, 1));
    110     }
    111 }
    112 
    113 template <typename T>
    114 void MemMgr::logout(T* ptr_obj)
    115 {
    116     std::map<void*, count>::iterator iter = cmap.find(ptr_obj);
    117     if (iter != cmap.end()) {
    118         --(iter->second);
    119         if (iter->second == 0) {
    120             T *p = (T*)(iter->first);
    121             delete p;
    122         }
    123     }
    124 }
    125 
    126 #endif // MEMMGR_H

    MemMgr.cpp

     1 #include "MemMgr.h"
     2 
     3 #include <iostream>
     4 
     5 using namespace std;
     6 
     7 MemMgr::MemMgr()
     8 {
     9     cout << "MemMgr cons" << endl;
    10 }
    11 
    12 MemMgr::~MemMgr()
    13 {
    14     cout << "MemMgr des" << endl;
    15 }
  • 相关阅读:
    Instruments Tutorial for iOS: How To Debug Memory Leaks
    How to Use Instruments in Xcode
    Demystifying iOS Application Crash Logs
    “iOS 推送通知”详解:从创建到设置到运行
    推送通知iOS客户端编写实现及推送服务器端编写
    cocos2d-iphone 与 UI组件
    ScrollLayer
    TexturePacker
    mybatis的配置
    spring+redis
  • 原文地址:https://www.cnblogs.com/qrlozte/p/4114386.html
Copyright © 2011-2022 走看看