1

デストラクタBlockを呼び出すクラスがあります。SDL_FreeSurface(surface)でブロックのmain()インスタンスを作成すると、オブジェクトは適切に機能しますが、データ メンバーとしてControl持つ別のクラスで使用するとvector<Block> block_vector、 のインスタンスを に追加するとプログラムがクラッシュしBlockますblock_vectorBlockを呼び出すときのデストラクタの問題を絞り込みましたSDL_FreeSurface(surface)。ベクターにオブジェクトを追加することは何か関係がありますか? 何が問題ですか?

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

    }

    }

    } 
4

1 に答える 1

3

ブロック オブジェクトの 1 つをベクターに挿入すると、コピーが作成されます。コピー コンストラクターを提供しなかったため、コンパイラによって生成されたコピー コンストラクターが使用されます。コンパイラによって生成されたコピー コンストラクターは、単にポインターをコピーします。実際の SDL サーフェスはコピーされません。

これは、元の Block オブジェクトと、ベクターに挿入された Block オブジェクトの両方が、同じ SDL サーフェスへのポインターを持っていることを意味します。これらの Block オブジェクトのいずれかの有効期間が終了すると、デストラクタが呼び出され、SDL サーフェスが解放されます。もう一方の Block オブジェクトにはダングリング ポインタがあり、その有効期間が終了してデストラクタが呼び出されると、ダングリング ポインタで SDL_FreeSurface を呼び出します。

これはほぼ間違いなく、クラッシュの原因です。そのため、3 つのルールに従い、コピー コンストラクターと代入演算子の両方を適切に実装する必要があります。実装はあなた次第です。ほとんどの場合、オブジェクトの完全なディープ コピーを作成することをお勧めします。std::shared_ptrしかし、SDL サーフェスのような重いオブジェクトの場合は、ある種の参照カウント メカニズムの実装を検討するかSDL_FreeSurfacedelete.

于 2012-10-09T05:19:50.950 に答える