I have a class Block which calls SDL_FreeSurface(surface) in the destructor. In the main() when I create an instance of Block, the object functions properly but when I used it in another class Control ,which has vector<Block> block_vector as a data member, the program crashes when I add an instance of Block into the block_vector. I narrowed down the problem which is the destructor of the Block when calling SDL_FreeSurface(surface). Does adding objects to the vector have anything to do with is? What is the problem?
class Block{
public:
Block(int x, int y);
~Block();
void Load_Image(MediaFunctions &M_Functions);
void SetPosition(int x, int y);
void BlitBlock(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool DetectionNames(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool DetectionHours(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool return_error();
private:
SDL_Surface *block_surface_names;
SDL_Surface *block_surface_hours;
SDL_Surface *block_names_detected;
SDL_Surface *block_hours_detected;
SDL_Rect block_rect_names;
SDL_Rect block_rect_hours;
bool error;
};
//the problem
Block::~Block(){
SDL_FreeSurface(block_surface_hours);
SDL_FreeSurface(block_surface_names);
SDL_FreeSurface(block_hours_detected);
SDL_FreeSurface(block_names_detected);
}
//when doing this
void Control::HandleEvents(SDL_Event &event, MediaFunctions &M_Functions){
if(event.type == SDL_KEYDOWN){
if( event.key.keysym.sym == SDLK_a ){
//append a block instance
BlockVector.push_back(Block (Block(100,100)));
BlockVector.at(block_index).Load_Image(M_Functions);
block_index++;
}
}
}
When you insert one of your Block objects into the vector, a copy is made. Since you didn’t provide a copy constructor, the compiler generated copy constructor is used. The compiler generated copy constructor will simply copy your pointers over. It won’t copy the actual SDL surfaces.
That means that your original Block object, and the Block object that is inserted into your vector both have pointers to the same SDL surfaces. When the lifetime of one of those Block objects ends, the destructor is called, which frees the SDL surface. Now the other Block object has a dangling pointer, and when its lifetime ends, and the destructor is called, you call SDL_FreeSurface on a dangling pointer.
This is almost certainly what is causing your crash. That’s why you need to follow the Rule of Three, and properly implement both a copy constructor, and an assignment operator. The implementation is up to you. In most cases, I would recommend doing a full, deep copy of your objects. But for such heavyweight objects as SDL surfaces, I would recommend you look at implementing some kind of reference counting mechanism, or use
std::shared_ptrwith a custom deleter that callsSDL_FreeSurfaceinstead ofdelete.