singleton() destructor

Apr 4, 2011 at 8:04pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
1 #include <iostream>
  2 #include <new>
  3 #include <cstdlib>
  4 
  5 using namespace std;
  6 
  7 
  8 class Singleton
  9 {
 10 protected:
 11         static Singleton *instance;
 12         Singleton(){}
 13 public:
 14         static Singleton* getMyInstance();
 15         void display(){cout<<"im using it"<<endl;}
 17         virtual ~Singleton(){cout<<"singleton destructor"<<endl;delete instance;instance = NULL;}
 18 };
 19 
 
 26 Singleton* Singleton::instance = NULL;
 27 
 28 Singleton* Singleton::getMyInstance()
 29 {
 30         if(!instance)
 31         {
 32                 try
 33                 {
 34                         instance = new Singleton;
 35                 }
 36                 catch (bad_alloc xa)
 37                 {
 38                         cout<<"allocation failed"<<endl;
 39                         exit(0);
 40                 }
 41 
 42                 cout<<"new object only created once"<<endl;
 43         }
 44         return instance;
 45 }
 
 46 class derived:public Singleton
 47 {
 48 private:
 49         int val;
 50         Singleton *ptr;
 51 public:
 52         derived(){}
 53         ~derived(){cout<<"derived destructor"<<endl;delete ptr;}
 54         void setVal();
 55 };
 56 void derived::setVal()
 57 {
 58         ptr = getMyInstance();
 59         ptr->display();
 60 
 61 }
 62 
 63 int main()
 64 {
 65 derived *obj, *obj1;
 66 obj = new derived;
 67 obj->setVal();
 68 delete obj;//this causes endless loop
 69 cout<<"************"<<endl;
 70 obj1 = new derived;
 71 obj1->setVal();
 72 
 73 return 0;
 74 }


singleton destructor
is printed infinitely
Apr 4, 2011 at 8:12pm
Yes, because Singleton's destructor recursively calls itself via
delete instance;
Apr 4, 2011 at 8:17pm
IMHO a Singleton should provide no public destructor at all. And no destructor method either.
Apr 4, 2011 at 8:17pm
1) i dont get it. Why does it call itself recursively? Why does it not not free the memory on the heap?
2) Since the destructor is virtual and the *obj is of type derived why will the destructor of Singleton be called. it shld be the destructor of derived.
Apr 4, 2011 at 8:21pm
jack, I think you should look a bit more into OO in C++ -
1) If you delete your object, it attempts to delete itself, which will cause it to attempt to delete itself, which will cause it to delete itself, which will...

2) ALL destructors from the class hierarchy are automagically invoked, starting from the lowest (most derived) class destructor and ending at the base class destructor.
Apr 4, 2011 at 9:38pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class lion
  9 {
 10 public:
 11         lion(){cout<<"lion construct"<<endl;}
 12         virtual void roar(){cout<<"lion roar"<<endl;}
 13         virtual ~lion(){cout<<"lion destructor"<<endl;}
 14 };
 15 
 16 class babylion:public lion
 17 {
 18 public:
 19         babylion(){cout<<"baby lion construct"<<endl;}
 20         void roar(){cout<<"baby lion meow"<<endl;}
 21         ~babylion(){cout<<"babylion destructor"<<endl;}
 22 };
 23 
 24 void disp(lion *li)
 25 {
 26         li->roar();
 27 }
 28 

 30 
 31 int main()
 32 {

 35 
 36 lion *lobj = new babylion;
 37 disp(lobj);
 38 cout<<"***********"<<endl;
 39 delete lobj;//delete does not cause a loop
return 0;
}


lion construct
baby lion construct
baby lion meow
***********
babylion destructor
lion destructor



I delete the object and there is no recursion here.
Last edited on Apr 4, 2011 at 9:39pm
Apr 4, 2011 at 9:42pm
You don't get a loop there because the destructor isn't deleting itself.

remember delete calls the destructor. So if you delete yourself in the destructor, it will call the destructor, which will delete itself, which will call the dtor, which will delete, which will call the dtor, etc, etc.
Apr 4, 2011 at 10:03pm
@ Disch

thanks i got it now....and perhaps a solution to destroy the singleton would be to have another method/class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Singleton {
    public:
        static Singleton* Instance();
    protected:
        Singleton() { }

        friend class SingletonDestroyer;
        virtual ~Singleton() { }
    private:
        static Singleton* instance;
        static SingletonDestroyer _destroyer;
    };

    Singleton* Singleton::instance = NULL;
    SingletonDestroyer Singleton::_destroyer;

    Singleton* Singleton::Instance () {
        if (!instance) {
            instance = new Singleton;
            _destroyer.SetSingleton(instance);
        }
        return instance;
    }


    class SingletonDestroyer {
    public:
        SingletonDestroyer(Singleton* = 0);
        ~SingletonDestroyer();

        void SetSingleton(Singleton* s);
    private:
        Singleton* _singleton;
    };

    SingletonDestroyer::SingletonDestroyer (Singleton* s) {
        _singleton = s;
    }

    SingletonDestroyer::~SingletonDestroyer () {
        delete _singleton;
    }

    void SingletonDestroyer::SetSingleton (Singleton* s) {
        _singleton = s;
    }
Apr 4, 2011 at 10:31pm
Well that's kind of pointless. You could just not use a pointer and have the same effect.

If you want this to be derivable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
template <typename T>
class Singleton
{
protected:
  Singleton() { }

private:
  Singleton(const Singleton<T>&);
  void operator = (const Singleton<T>&);

public:
  T& Get()
  {
    static T theObject;
    return theObject;
  }
};

//====
//  to derive a class
class MySingleton : public Singleton<MySingleton>
{
public:
  void Whatever();
};


//=====
//  usage

int main()
{
  MySingleton::Get().Whatever();
}



Of course, be sure you're not abusing the Singleton pattern. Legitimate uses for singletons are actually much more rare than you might think.

Newbies tend to treat them just as if they were a "cleaner" way to have a bunch of globals.
Apr 5, 2011 at 12:35am
i also realize that the infinite call takes place because of the static instance pointer. If the pointer has been declared non as auto than there is no issue of the infinite call.

The reason i think is because static pointers exist even before the object is created and has a life span till the after end of the program. Sine you call delete on instance it will then call the delete over and over again.

let me know if my analysis is right? Thanks
Apr 5, 2011 at 1:44am
It's realted with how to delete singleton implicitly or explicitly. The following link is a good refer.

http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt
Topic archived. No new replies allowed.