# [c++/sdl_font] memleaking vector

This topic is 4130 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

hey, i have just started with vectors and it all went okay until i came to the part where i wanted to display FPS in the corner of the screen. i know when i did this with ordinary arrays, i had to freesurface before i reloaded the new value of the variable, but now it seems i have to do something else aswell? the code: main.cpp

TTF_Font *FontText;
std::vector<SDL_Surface*> text;

//the var
std::stringstream ssFPS;
ssFPS << getFPS();

//set font
FontText = TTF_OpenFont(font/font1.ttf, 12);

//set font style
TTF_SetFontStyle (FontText, TTF_STYLE_NORMAL);

//set font color/alpha chan
SDL_Color local_fg = {setRed,setGreen,setBlue,0};

//render text
//freesurface here, old way.
//i did try by erasing the element out of the vector, but the memleak was still there
text.push_back(TTF_RenderText_Solid(FontText, setFontVar.c_str(), local_fg));

//set coords
fontX.push_back(setFontX);
fontY.push_back(setFontY);

//blit text vectors
for(short i= 0; i!= text.size(); i++)
BlitIMG(text[i], fontX[i], fontX[i]);



##### Share on other sites
vector will clean up after itself, not after you. If you have a vector of pointers, vector will never destroy what these pointers point to. Indeed, it cannot know whether it should or not: you might be pointing to a statically allocated object or might still be using it through a pointer that the vector is unaware of.

When SDL gives you a pointer to a freshly allocated surface, font or howler monkey, you have the responsibility of deallocating it when you're done using it (which is why smart pointers are a good thing). Check the SDL documentation for further details.

##### Share on other sites
emm, i forgot to mention that i also tried adding a text.clear() into the loop, but it was the same.

##### Share on other sites
I think Fruny already answered your question. If you maintain a vector of pointers, it is your responsibility to delete() (or free()) the pointers. The vector will take care of itself.

A good rule to enforce is: every time you write 'new', you should also be writing 'delete' (in the appropriate place, of course). The same goes for 'malloc/calloc' and 'free', should you be possessed to use them. There are, of course, exceptions to this rule, but by the time you encounter one, you'll probably have the ritual firmly drilled in, and hence, the mentality successfully installed. [I think that's enough commas for one sentence]

Regards

##### Share on other sites
yes, but how would i implement this?
requesting examples.

EDIT:
i don't wanna use Boost atm, but you can supply those examples too, i guess.
ty.

##### Share on other sites
For every pointer that you use SDL to initialize and then push into the vector, you need to use SDL to uninitialize that pointer when you're done with it, just like you would any pointer that is not in a vector. I've never used SDL, so I don't know the exact syntax, but a sufficient pattern to follow would be:

//Initialization:std::vector<Something*> VectorOfPointers;VectorOfPointers.push_back(CreateAnObjectAndReturnAPointer("a parameter"));VectorOfPointers.push_back(CreateAnObjectAndReturnAPointer("a parameter"));VectorOfPointers.push_back(CreateAnObjectAndReturnAPointer("a parameter"));VectorOfPointers.push_back(CreateAnObjectAndReturnAPointer("a parameter"));//Deinitialization:while (!VectorOfPointers.empty()){  DeleteAnObject(VectorOfPointers.back());  VectorOfPointers.pop_back();}

In many cases, CreateAnObjectAndReturnAPointer() would be a simple call to new, and thus DeleteAnObject() would be a call to delete. In your case, they would be SDL-specific functions. But as Fruny said, standard containers only manage memory and resources that they allocate, which in this case is the space to store pointers (not the things being pointed to). Thus when a vector cleans up after itself, it only deallocates the memory for the pointers, not the stuff that the pointers point to.

##### Share on other sites
nope, does not work.
i added: "delete text.back();" and it's making my app crash.

##### Share on other sites
Quote:
 Original post by theSecondtnope, does not work.i added: "delete text.back();" and it's making my app crash.

Is that how you normally delete SDL resources?

If so, what is the value of text.back() at the time you try to delete it? It's possible that it got altered somewhere along the way.

##### Share on other sites
i normally delete sdl resources with SDL_FreeSurface((SDL_Surface*)Var) (in this case Var was text[i] and the function was in a loop), but since that didn't work i'm puzzled :|

i printed out the values, they match
Quote:
 1: 36449968 2: 364499681: 36446192 2: 364461921: 11526728 2: 11526728

edit: gonna try auto_ptr
edit2: and yet i fail.
code:
" std::vector< std::auto_ptr<SDL_Surface> > getFontText(){ return std::vector< std::auto_ptr<SDL_Surface> > (text); }"
errors:
Quote:
 \include\c++\3.4.2\bits\stl_construct.h In function void std::_Construct(_T1*, const _T2&) [with _T1 = std::auto_ptr, _T2 = std::auto_ptr]': 86 D:\zdelamo\Dev-Cpp\include\c++\3.4.2\bits\stl_uninitialized.h instantiated from _ForwardIterator std::__uninitialized_copy_aux(_InputIterator, _InputIterator, _ForwardIterator, __false_type) [with _InputIterator = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, _ForwardIterator = std::auto_ptr*]' 112 \include\c++\3.4.2\bits\stl_uninitialized.h instantiated from _ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, _ForwardIterator = std::auto_ptr*]' 221 \include\c++\3.4.2\bits\stl_vector.h instantiated from std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::auto_ptr, _Alloc = std::allocator >]' 81 \include\c++\3.4.2\bits\stl_construct.h passing const std::auto_ptr' as this' argument of `std::auto_ptr<_Tp>::operator std::auto_ptr_ref<_Tp1>() [with _Tp1 = SDL_Surface, _Tp = SDL_Surface]' discards qualifiers

[Edited by - theSecondt on September 27, 2006 2:42:56 PM]

##### Share on other sites
Quote:
 Original post by theSecondti normally delete sdl resources with SDL_FreeSurface((SDL_Surface*)Var) (in this case Var was text[i] and the function was in a loop), but since that didn't work i'm puzzled :|

Indeed that is puzzling, because SDL_FreeSurface((SDL_Surface*)text.back()) would be precisely what you need in the example I provided.

However, what this could mean might be that it's not the pointer itself or what it points to that is causing the problem, but something that you did earlier in the program. Sometimes, if you write to memory that shouldn't be written to (usually writing beyond the bounds of an array), nothing bad will happen at first, but the moment you try to free some memory, it might catch the error (some of the memory tracking data that the memory manager uses might have gotten overwritten, so now it has garbage and doesn't know how to delete memory), and cause the access violation that you're seeing.

Quote:
i printed out the values, they match
Quote:
 1: 36449968 2: 364499681: 36446192 2: 364461921: 11526728 2: 11526728

That's good, at least.

Quote:
 edit: gonna try auto_ptredit2: and yet i fail.code:" std::vector< std::auto_ptr > getFontText(){ return std::vector< std::auto_ptr > (text); }"errors:...

Unfortunately, std::auto_ptr won't work for containers, I believe due to not copying correctly, or at all (elements in standard containers have operator = and/or copy constructors called on them; if the type doesn't allow that, or doesn't handle those cases appropriately, problems will result). Either way, the only thing std::auto_ptr would do is try to call delete on the pointer, but what you need to do is call SDL_FreeSurface() on the pointer. You'd end up with a problem anyway, even if you used a smart pointer that does work with containers (such as boost::shared_ptr).

##### Share on other sites
Quote:
 Original post by AgonyYou'd end up with a problem anyway, even if you used a smart pointer that does work with containers (such as boost::shared_ptr).

Actually Boost's smart pointers are sufficiently smart that they could be used here. All you'd have to do is pass SDL_FreeSurface when constructing the pointer (boost::shared_ptr< SDL_Surface > shared_ptr(TTF_RenderText_Solid(FontText, setFontVar.c_str(), local_fg), SDL_FreeSurface);).

theSecondt: What exactly is going wrong and how are you diagnosing it? Going from an array to a vector should be trivial.

Σnigma

##### Share on other sites
sigh.
well, i can give you the whole code, since this were only snippets from different parts of different classes.

enigma: i know for sure that the problem occurs when i try to draw values from vars on screen, because they are in a loop.
static text(?) works fine(if i haven't done something horrific before in the code).

i have _tried_ to use gdb, but it fails at the 6th frame.. it seems there's a problem with the SDL_image library(or so i assume) i am using.