Some findings about shared_ptr and deque

creating a deque (similar to vector) of shared pointers to an object
the nice thing about shared pointers ist that they free their use memory once erased

<deque< shared_ptr<oneBuffer> > allBuffers>

creating a deque of pointers (i think)

std::deque<oneBuffer*> allBuffers;

deque can be use in a similar as vectors
the are most efficient when used to access front or end, but not as fast to get other elements

allBuffers.pop_back();
allBuffers.pop_front();

predicate
“The Predicate concept describes a function object that takes a single iterator argument that is dereferenced and used to return a value testable as a bool.”

bool isBufferDead(const shared_ptr<oneBuffer>& _buffer){
    return _buffer->deleteMe;
}

if you want a predicate with an additional parameter
similar to find

struct is_ID
{
    //all this to check if any buffer element has the passed in id
    is_ID(const int& a_wanted) : _id(a_wanted) {}
    int _id;
    bool operator()(const shared_ptr<oneBuffer>& _buffer)
    {
        return _buffer->myID == _id;
    }
};

using the predicate to erase element is true to a specific state

allBuffers.erase(remove_if(allBuffers.begin(), allBuffers.end(), isBufferDead), allBuffers.end());

using the predicate to erase element that matches SOME_NUMBER

allBuffers.erase(remove_if(allBuffers.begin(), allBuffers.end(), is_ID(SOME_NUMBER)), allBuffers.end());

ofRemove() can be used if you use vector instead of deque

ofRemove(allBuffers, isBufferDead);
5 Likes

maybe using shrink_to_fit on the deque will help. i learned pop_front() does not deallocate storage that was allocated by push_back()

slices.pop_front();
slices.shrink_to_fit();
1 Like

i ma using the deque shared_ptr to handle many memory intensive objects.
and i find calling pop_front() and pop_back() does not release memory properly, since i can see “App Memory” constantly increase in macOS activity monitor.

this seems to be a problem with deque:

1 Like

That’s interesting, so the shrink_to_fit didn’t fix it for you at all? No effect on memory?

1 Like

From the stackoverflow chat:

std::deque is not special
it delegates the job to allocator, which, unless you use the non-default one, is std::allocator, which uses ::operator new, which on all the implementations I’m familiar with uses malloc.
malloc in general won’t give the memory back to the OS if it doesn’t need to
TL;DR you don’t need to worry about this 99.99% of the time

not really.

i did try a fixed array of objects and there was no memory leak.
so it must be something with how i handle

also tried swap from here:

//in ofApp.h
//declaration
deque< shared_ptr<oneSlice> > slices;
shared_ptr< oneSlice > aSlice;

//in ofApp.cpp
//create
aSlice.reset(new oneSlice() );
aSlice->myID = newID;
aSlice->widthCurrent = 0;
aSlice->setup();
slices.push_back(aSlice);

//delete
slices.back().reset();
slices.pop_back();
//slices.shrink_to_fit();
deque< shared_ptr<oneSlice> >( slices ).swap( slices );

which seemed to help a bit. but overall app memory still increases slowly. but not the one from my app.
http://www.gotw.ca/gotw/054.htm

do you need to use shared_ptr for any reason? using objects directly like in deque<oneSlice> + emplace_back to create the objects directly in the data structure is usually faster and even if the deque leaves that space allocated when deleting it will just be reused by the next object you put in it.

thanks for your response.

true i do not need shared_ptr. i read somewhere that it takes care of it’s own memory garbage collection.
but since my deque of objects also has ofFbo, ofImage and ofMesh in it, it might not really work.

so, i tried removing shared_ptr and replaced pop_back and pop_front with emplace_back and emplace_front but still have an app memory build up.
in the mean time i re-wrote the code to use a fixed array size. and no memory leak.
so it must be something related to how i pop and push.

Can’t it be something internal to your class? Have you tried pushing and popping another object, ofImages for instace?

Thanks! That is interesting.

shared_ptr deletes after itself but the same does an object that it’s not a pointer and it’s faster to access

also any std collection usually doesn’t delete memory once it’s allocated but that’s just an optimization so it doesn’t need to allocate it later which is slow. it’s hard to tell what’s going on in your case but it’s hard to believe there’s a leak in an std container