1

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++;

    }

    }

    } 
lambda
  • 1,225
  • 2
  • 14
  • 40

1 Answers1

3

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_ptr with a custom deleter that calls SDL_FreeSurface instead of delete.

Community
  • 1
  • 1
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • The crash occurs when the object is created in the vector. the destructor isnt even called yet. i added a copy constructor and the crash still occurs – lambda Oct 15 '12 at 23:14