views:

503

answers:

5

This code is causing a memory leak for me, and I'm not sure why.

[EDIT] Included code from here into question:

#include "src/base.cpp"

typedef std::map<std::string, AlObj*, std::less<std::string>, 
  gc_allocator<std::pair<const std::string, AlObj*> > > KWARG_TYPE;

AlInt::AlInt(int val)   {
    this->value = val;
    this->setup();
}

// attrs is of type KWARG_TYPE
void AlInt::setup() {
    this->attrs["__add__"] = new AddInts();
    this->attrs["__sub__"] = new SubtractInts();
    this->attrs["__mul__"] = new MultiplyInts();
    this->attrs["__div__"] = new DivideInts();
    this->attrs["__pow__"] = new PowerInts();
    this->attrs["__str__"] = new PrintInt();
}

int main() {
    while (true) {
        AlObj* a = new AlInt(3);
    }
}

AlInt inherits from AlObj, which in turn inherits from gc. When I comment out the contents of setup() then I don't have a memory leak, this leads me to believe the issue is with the map not cleaning up, however I'm using the gc allocator, so I'm not sure where to look next. Thoughts?

+4  A: 

The 'gc allocator' is allocating and looking after objects of this type:

std::pair<const std::string, AlObj*>

Just because this object has a pointer in it does not mean it the allocator will call delete on it.

If you want the object created in setUp() to be GC then you need to allocate them via the GC. Or learn to use boost:ptr_map or shared_ptr.

A map destroys (not deletes) the object it owns. In this case it owns the pointer not what the pointer points at. So when the map is destroyed it deallocates everything associated with the map and the object it owns (for pointers this means it does nothing).

If you have a map (or other container) that contains pointers. You must manually delete the pointers otherwise there will be a memory leak. Alternatively you can use boost::ptr_map or a map that contains a share_ptr

Martin York
So I need a destructor on AlObj, that just does delete attrs?Also, here's *all* the code: http://github.com/alex/alex-s-language/tree/local%2Fcpp-generation/alexs_lang/cpp if someone wants to take a peak.
Alex Gaynor
Or use a boost::ptr_map
Martin York
I second Martin's suggestion
Leon Timmermans
Isn't the point of using the Boehm GC allocator that it will delete what the pointer points to when the map is destroyed?
Alex Gaynor
Not quite. 'delete' will invoke the destructor of an object (which may release resources other than memory, file handles, for instance).GC will simply reclaim memory which is no longer pointed to by any live pointers in your app.
Don Wakefield
So essentially I should create a destructor that iterates over attrs, and deletes each item?
Alex Gaynor
A: 

Actually I'm not sure I follow, AlObj has a member attrs which is a map, not a pointer to a map, so how would I deallocate it?

Alex Gaynor
A: 

Essentially what I'm saying is, the AlObj seems to be destructed, but not it's members(since it doesn't leak unless I put stuff in attrs).

Alex Gaynor
A: 

The allocator is deleting your pairs. But deleting a pair doesn't delete members of the pair that happen to be pointers.

Jonathan
But surely it makes the members of the pair unreachable so they will be eligible for garbage collection?
Jon Harrop
A: 

Ok so it sounds like I need to delete the pointers myself, but what if the pointer points to something that's also being pointed at elsewhere, I don't want to actually free the memory in that case, which I think was the point of the GC.

Alex Gaynor