Jump to content
  • Advertisement
Sign in to follow this  
theSecondt

[c++/sdl_font] memleaking vector

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

If you intended to correct an error in the post then please contact us.

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, fontX, fontX);


Share this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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
Admiral

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by theSecondt
nope, 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 this post


Link to post
Share on other sites
i normally delete sdl resources with SDL_FreeSurface((SDL_Surface*)Var) (in this case Var was text 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: 36449968
1: 36446192 2: 36446192
1: 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<SDL_Surface>, _T2 = std::auto_ptr<SDL_Surface>]':
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<const std::auto_ptr<SDL_Surface>*, std::vector<std::auto_ptr<SDL_Surface>, std::allocator<std::auto_ptr<SDL_Surface> > > >, _ForwardIterator = std::auto_ptr<SDL_Surface>*]'
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<const std::auto_ptr<SDL_Surface>*, std::vector<std::auto_ptr<SDL_Surface>, std::allocator<std::auto_ptr<SDL_Surface> > > >, _ForwardIterator = std::auto_ptr<SDL_Surface>*]'
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<SDL_Surface>, _Alloc = std::allocator<std::auto_ptr<SDL_Surface> >]'

81 \include\c++\3.4.2\bits\stl_construct.h passing `const std::auto_ptr<SDL_Surface>' 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 this post


Link to post
Share on other sites
Quote:
Original post by theSecondt
i normally delete sdl resources with SDL_FreeSurface((SDL_Surface*)Var) (in this case Var was text 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: 36449968
1: 36446192 2: 36446192
1: 11526728 2: 11526728

That's good, at least.

Quote:

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:
...


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 this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!