-1

I'm trying to implement autorelease pool in c++, and have trouble with deallocating. So we have root-class object:

class object {
 public:
    object() {
        retainCount_ = 0;
    }
    ~object() {
        std::cout << "object " << Description() << " is dealocated" << std::endl;
    }
    /* code with retain/release here */
    int retainCount() {
        return retainCount_;
    }
    std::string Description() {
        std::stringstream ss;
        ss << this;
        return ss.str();
    }
 private:
    int retainCount_;
};

And some realization:

class Integer : public object {
 public:
    int i;
    Integer(int ii) : i(ii) {}
    ~Integer() {
        std::cout << "Integer " << Description() << " is dealocated" << std::endl;
    }
};

And of course release pool class, which works with root-class pointers:

class release_pool {
 public:
    void insert(object* obj) {
        pointers_.insert(obj);
    }
    void flush() {
        std::set<object*>::iterator it = pointers_.begin();
        std::set<object*>::iterator tmp;
        const int N = pointers_.size();
        for (int i = 0; i < N; i++) {
            tmp = it;
            it++;
            if ((*tmp)->retainCount() == 0 ) {
                object* obj = *tmp;
                std::cout << "delete obj: " << obj->Description() << std::endl;
                pointers_.erase(tmp);
                delete obj;
            }
        }
    }
 private:
    std::set<object*> pointers_;
};

main.cpp code for test:

int main () {
    release_pool pool;

    Integer* obj = new Integer(5);
    pool.insert(obj);
    std::cout << "before flush: " << obj->i << "\n";

    pool.flush();

    std::cout << "after flush: " << obj->i << "\n";    
    return 0;
}

After build, I get next:

before flush: 5
delete obj: 0x7f9a84c025d0
object 0x7f9a84c025d0 is dealocated
after flush: 5

At the end: destructor of root-class is invoked, but of Integer not. Hence, we have leaked memory, which is allocated for Integer object. Have you any ideas to fix it? How i can delete whole object, not root-part of it.

qub
  • 23
  • 2

1 Answers1

2

You need to make your object destructor virtual.

Joseph Willcoxson
  • 5,853
  • 1
  • 15
  • 29
  • before flush: 5 delete obj: 0x7fee74e00000 Integer 0x7fee74e00000 is dealocated object 0x7fee74e00000 is dealocated after flush: 5 – qub Jun 22 '17 at 15:06
  • why, value is retured ???? anyway. – qub Jun 22 '17 at 15:07
  • Without a virtual destructor, it will only call the destructor ~object() and not ~Integer(). – Joseph Willcoxson Jun 22 '17 at 15:09
  • i check with virtual already. Both of destructors are invoked, but object not died... i still can take obj->i after flush. and my pointer of integer object not NULL. – qub Jun 22 '17 at 15:12
  • @qub delete may set the pointer to NULL but it isnt required to do so. Also accesing members via an invalid (deleted) pointer is "only" undefined, but not guaranteed to have any particular effect – 463035818_is_not_an_ai Jun 22 '17 at 15:15
  • A pointer is just an address of a memory location. After you delete it, the memory location still exists, and the contents of the memory still exist until the system overwrites it. It doesn't magically turn to NULL. Once you delete the object, you tell the OS or runtime that it is free to do with the memory as it pleases. – Joseph Willcoxson Jun 22 '17 at 15:16
  • @Joe Willcoxson hmm, it's not safety. after delete i can call methods and parameters... Can i do more safety and forbid calling something after delete??? – qub Jun 22 '17 at 15:36
  • @qub No, there is no reasonable way for pool.flush() to affect the value of the variable 'obj.' You could have pool.insert() take its parameter by reference and then have pool.flush() set the reference to NULL / nullptr but that assumes that the reference is still valid when pool.flush() gets called, which is almost surely an unreasonable assumption to make. – jschultz410 Jun 22 '17 at 15:43
  • When you're playing with pointers, you have to be careful. C++ gives you full control of memory allocations for good and for bad. Try to only use your power for good. – Joseph Willcoxson Jun 22 '17 at 16:10