3

このプログラムを実行するたびに、次のエラーが発生しました。

セグメンテーション違反

テスト.cpp

#include <iostream>
#include <cstdint>
#include <SDL.h>
#include <SDL_image.h>

#include "Surface.h"
#include "Point2D.h"

int main() {
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        std::cerr << "Can not init SDL" << std::endl;
        return -1;
    }

    SDL_Surface *scr = SDL_SetVideoMode(800, 600, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);

    if ( scr == NULL ) {
        std::cerr << "Can not open window" << std::endl;
        return -1;
    }

    SDL_WM_SetCaption("Test Surface class", NULL);

    Surface screen;
    Surface image;

    screen.set(SDL_GetVideoSurface());

    if (image.load("./data/images/logo.png") == false) {
        std::cerr << "Can not open file" << std::endl;
        return -1;
    }

    bool run = true;
    uint32_t sticks = SDL_GetTicks();

    while(run) {
        if (screen.draw(image, Rectangle(0, 0, image.getWidth(), image.getHeight()), Point2D(0, 0)) == false) {
            std::cerr << "Can not draw to window" << std::endl;
            return -1;
        }

        if ((SDL_GetTicks() - sticks)/1000 > 5) {
            std::cerr << "End of time" << std::endl;
            run = false;
        }

        SDL_Flip(screen.sdlSurface());
    }

    std::cerr << "Done" << std::endl;
    SDL_Quit();

    return 0;
}

クラスSurfaceのソースコードがあります

#include "Surface.h"
#include "Color.h"

Surface::Surface() {
    this->surface = NULL;
}

Surface::~Surface() {
    SDL_FreeSurface(this->surface);
    this->surface = NULL;
}

bool Surface::draw(Surface source, Rectangle source_area, Point2D position) {
    SDL_Rect sr = source_area.sdlRect();
    SDL_Rect tr = {position.getX(), position.getY(), 0, 0};

    std::cout << sr.x << "," << sr.y << "," << sr.w << "," << sr.h << std::endl;
    std::cout << tr.x << "," << tr.y << "," << tr.w << "," << tr.h << std::endl;

    std::cout << source.sdlSurface() << std::endl;
    std::cout << this->surface << std::endl;

    // TR and SR are currently unused. Just for case of testing
    if (SDL_BlitSurface(source.sdlSurface(), NULL, this->surface, NULL) != 0) {
        return false;
    }

    return true;
}

bool Surface::fill(Color color, Rectangle area) {
    SDL_Rect tr = area.sdlRect();

    std::cout << tr.x << "," << tr.y << "," << tr.w << "," << tr.h << std::endl;
    std::cout << (int)color.sdlColor() << std::endl;

    if ( SDL_FillRect(this->surface, &tr, color.sdlColor()) != 0) {
        return false;
    }

    return true;
}

Rectangle Surface::getSize() {
    return Rectangle(0, 0, this->getWidth(), this->getHeight());
}

bool Surface::load(std::string file) {
    SDL_Surface *src = IMG_Load(file.c_str());

    if (src == NULL) {
        std::cout << "cyh" << std::endl;
        std::cout << IMG_GetError() << std::endl;
        return false;
    }

    this->surface = SDL_DisplayFormatAlpha(src);
    if (this->surface == NULL) {
        std::cout << "cyh1" << std::endl;
        std::cout << SDL_GetError() << std::endl;
        return false;
    }

    SDL_FreeSurface(src);
    src = NULL;
    return true;
}

void Surface::set(SDL_Surface *surface) {
    this->surface = surface;
}

void Surface::set(Surface surface) {
    this->surface = surface.sdlSurface();
}

問題はおそらく draw 関数にあります。この行を変更すると:

if (SDL_BlitSurface(source.sdlSurface(), NULL, this->surface, NULL) != 0) {

に:

if (SDL_BlitSurface(IMG_Load("./data/images/logo.png"), NULL, this->surface, NULL) != 0) {

すべて問題ないようです。どこに問題があるべきか提案していただけますか?

4

1 に答える 1

3

あなたは3 のルールに違反しています。

これを正しく機能させるには、コピー コンストラクターコピー代入演算子を定義する必要があります。

Surfaceを draw メソッドに渡すと、そのコピーが作成されます。Surface クラス ( SDL_Surface*) 内のリソースを管理しているため、クラスの複数のインスタンスが同じサーフェスを指しているため、デストラクタが呼び出されると、同じSDL_Surface*ものを複数回解放することになります。

編集:引数を const 参照で渡すことをお勧めします。Surfaceオブジェクトを描画するときにオブジェクトのコピーを作成する必要はありません。

これ:

bool Surface::draw(Surface source, Rectangle source_area, Point2D position);

これになります:

bool Surface::draw(const Surface &source, const Rectangle &source_area, const Point2D &position);

これは、他の機能にも適用できます。

于 2013-06-03T17:25:56.160 に答える