0

I was attempting to write a singleton pattern which displays current time. The problem occurs on deleting heap memory allocated to the static pointer variable global_time_variable via calling the static member function destroy_instance().

class current_date_time {

  private:

    current_date_time() {
       std::cout << "constructor invoked!!\n";
    };

    ~current_date_time() {
       std::cout << "destructor invoked!!\n";
       delete global_time_variable;
    };

  public:

    static void create_instance();
    static void destroy_instance();
    static current_date_time* global_time_variable;

    void time_output(){
      std::time_t t = std::time(nullptr);
      std::tm tm = *std::localtime(&t);
      std::cout << std::put_time(&tm, "%c %Z") << "\n";
    }

};


current_date_time* current_date_time::global_time_variable = NULL;

void current_date_time::create_instance() {
   if(current_date_time::global_time_variable == NULL)
      global_time_variable =  new current_date_time();
}

void current_date_time::destroy_instance() {
    (*global_time_variable).~current_date_time();
}


int main() {

   current_date_time::create_instance();
   current_date_time::global_time_variable->time_output();
   current_date_time::destroy_instance();
   return 0;
}

I am curious to know as to why was destructor invoked multiple times?

On going through James Kanze's answer to the question C++ Deleting Static Data The other possible options are:

  1. Not trying to manually invoke - In this case, the object stays in heap wherein i am not sure who deletes it
  2. Use smart pointers - In this case, these pointers have a destructor wrapped around them and its invoked automatically

UPDATE:

My second question would be: In case if I wouldn't invoke a destructor(which seems to be one of recommended options), wouldn't it result to memory leaks?

Since static variables are destroyed after program lifetime while object pointed by global_time_variable wouldn't get destroyed.

xAditya3393
  • 149
  • 4
  • 12
  • 2
    `(*global_time_variable).~current_date_time();` calls it and `delete global_time_variable;` calls it again, which should result in infinite recursion. – tkausl Jul 11 '18 at 20:42
  • @tkausl Silly of me not taking a note of it. I guess not calling it would be ideal. In which case who deletes the memory allocated? – xAditya3393 Jul 11 '18 at 21:03

1 Answers1

0

Since new is invoked in create_instance, delete should be called in destroy_instance instead of a manual destructor invocation.

In general, destructors are invoked by delete so they should not themselves be calling delete on the the object being destroyed.

#include <iomanip>
#include <ctime>
#include <stdio.h>
#include <iostream>
#include <string.h>

class current_date_time {

  private:

    current_date_time() {
       std::cout << "constructor invoked!!\n";
    };

    ~current_date_time() {
       std::cout << "destructor invoked!!\n";
    };

  public:

    static void create_instance();
    static void destroy_instance();
    static current_date_time* global_time_variable;

    void time_output(){
      std::time_t t = std::time(nullptr);
      std::tm tm = *std::localtime(&t);
      std::cout << std::put_time(&tm, "%c %Z") << "\n";
    }

};


current_date_time* current_date_time::global_time_variable = NULL;

void current_date_time::create_instance() {
   if(current_date_time::global_time_variable == NULL)
      global_time_variable =  new current_date_time();
}

void current_date_time::destroy_instance() {
    delete global_time_variable;
    global_time_variable = NULL;
}


int main() {

   current_date_time::create_instance();
   current_date_time::global_time_variable->time_output();
   current_date_time::destroy_instance();
   return 0;
}
merlin2011
  • 71,677
  • 44
  • 195
  • 329