0

[SOLVED] Forgot to implement a copy constructor and an assignment operator. The instance which is being assigned to using default copying will get the same pointer as the instance which created the surface it points to. Once one of them destructs or calls redraw(), the other keeps the pointer to freed memory, and it causes a segmentation fault.


I have a class for text labels in my application. When it's properties are changed, it automatically redrawing itself into it's private surface.

Generally, redrawing looks like this:

void Text::redraw() {
 if(_font==0) return;
 if(_image) {      
  SDL_FreeSurface(_image); //this line throwing a segfault
  _image = 0;
 }

 _image = TTF_RenderUTF8_Blended(_font, _text.c_str(), _color);
}

But the code crashing on freeing the surface (only a valid ones, of course, as the pointer equals to 0 when it doesn't have a surface to free).

It's also strange that on some machines the code's doing well and frees a memory. But on the others it crashes.

If I comment out lines where it frees a surface, the application works well, but the memory leaks. I didn't found nor explanation, neither a solution for that.


I do set _image to 0 in constructor. There is no code that changes _image value or frees the surface except redraw() function (and destructor).

Somehow freeing memory crashing on XP only. If I comment out freeing part, it doesn't crash. Both variants works on win7 (both x86 and x64) well.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

1 Answers1

1

Taking the premise that that we generally know that SDL works well this leaves us with the following options (I can't think of any others, but there may well be some)

  • Possibility that the library was built incorrectly
  • The enclosing Text is somehow being copied somewhere else in the code (breaking the rule of 3
  • Something else is calling SDL_FreeSurface with the same pointer
  • Something else is trampling on the heap (possibly but unlikely as this is the only instance you've said that fails);

So I'd generally debug this by adding some (grep'able) printfs as follows and then check the output line by line:

void Text::redraw() {
 if(_font==0) return;
 if(_image) {      
fprintf(stderr,"## $%x freeing $%x",this, _image);
  SDL_FreeSurface(_image);
  _image = 0;
 }

 _image = TTF_RenderUTF8_Blended(_font, _text.c_str(), _color);
fprintf(stderr,"## $%x allocated $%x",this, _image);
}
Community
  • 1
  • 1
Richard Harrison
  • 19,247
  • 4
  • 40
  • 67
  • Yes, I do some logging (just cut it out to show the exact problem, as logging doesn't change pointer's value (or the surface it points to)). – Alexander Tkachov Feb 13 '13 at 13:25
  • Could it be that SDL_Quit was called before? – rkellerm Feb 13 '13 at 13:29
  • @rursw1 I don't think so. The application crashes when you try to update a label right after creating, not when the process is being terminated (and SDL_Quit is called right before the application is closed). – Alexander Tkachov Feb 13 '13 at 13:37
  • @richard-harrison the library frees another surfaces well (and it actually was build by someone else as I've downloaded it from libsdl.org); Nor Text, neither instances of classes which contain it as a private field are being copied, though I'll check it once again now; The surface shouldn't be freed by anything else, but I'll check it once again too. – Alexander Tkachov Feb 13 '13 at 13:42
  • Yep, I'm that stupid that forgot to implement a copy constructor and an assignment operator. I do use an assignment. Thanks! – Alexander Tkachov Feb 13 '13 at 14:08
  • excellent; well done for checking and finding it. it's an easy mistake to make. – Richard Harrison Feb 13 '13 at 15:55