2013-06-03 26 views
3

我每次運行這個程序,我得到了這個錯誤:SDL塊傳送面:分段故障

Segmentation fault

testing.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; 
} 

有類表面的源代碼

#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(); 
} 

Th問題可能在繪圖功能中。如果我改變這一行:

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

到:

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

一切似乎是確定。你能否給我一個建議,問題應該在哪裏?

+1

在調試器中運行它,所以我們將知道它是否爲空指針錯誤 –

回答

3

您正在違反The Rule of 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); 

這可太應用到你的其他功能。

+0

@BenjaminLindley剛剛注意到並更改了我的答案。我想我找到了問題。 –

+0

+1:但實際上,拷貝構造函數和賦值運算符應該像這樣被禁用(在C++ 03中被私有化,或者在C++ 11中被刪除),並且它應該被引用傳遞,除非OP爲該類實現引用計數,所有副本共享「SDL_Surface」。 –

+0

沒錯,剛剛更新了我的答案。 –