2012-02-18 72 views
0

我有一个为我管理SDL_Surface的类,我想让它不必担心释放表面。我有这样的代码至今:C++析构函数早期调用

//In Entity.h 
class Entity 
{ 
public: 
    int x, y, width, height; 

    Entity(std::string); 
    ~Entity(); 
    void render(); 

private: 
    SDL_Surface* texture; 
}; 

//In Entity.cpp 
Entity::~Entity() 
{ 
    printf("Destroying an Entity"); 
    SDL_FreeSurface(texture); 
} 

//In main.cpp 
Entity puppy("puppy.bmp"); 

void render() { 
    clearScreen(); 

    puppy.render(); 
} 

int main (int argc, char **argv) { 

    printf("started"); 
    init(); 

    bool done = false; 
    while(!done) 
    { 

     ... 

     // Draw the screen 
     printf("About to render"); 
     render(); 

     SDL_Flip(screen); 

    } 

    SDL_Quit(); 
    return 0; 
} 

当我运行它,我得到Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000260 0x000000010002fd9b in SDL_DisplayFormat()我是在假设析构函数是越来越早调用,它试图呈现一个空的纹理是否正确?代码工作正常,如果我没有析构函数,只是浪费内存。我也尝试过将它作为一个局部变量,并将它传递给渲染,但这并没有帮助。

编辑:代码运行只有一秒,然后崩溃。它不会等待退出循环。另外,使用gdb单步执行程序会让小狗因为某种原因至少被绘制一次。我上传的完整源在这里:http://dl.getdropbox.com/u/2223161/sdlgame.zip

+0

您似乎没有进行任何SDL初始化。 – 2012-02-18 00:41:26

+0

这看起来不像你的代码,因为它甚至不会编译(或链接,就此而言)。在_你的代码中,你确定没有“实体”的副本吗? – wilhelmtell 2012-02-18 00:47:59

+0

@KerrekSB我删除了一些代码,以防止它变得太长。完整的源代码位于http://dl.getdropbox.com/u/2223161/sdlgame.zip – Cole 2012-02-18 01:31:42

回答

2

您正在寻找问题的错误结局。在将puppy的初始化设置为main后,您的代码为我运行。

通过将puppy作为全局对象,它的构造函数在SDL_Init之前运行。构造函数调用load_image,它调用SDL_DisplayFormat。该文档警告:

您必须在使用SDL_DisplayFormat函数之前调用SDL_Init。如果你不这样做,你的程序将会因访问冲突而崩溃。

http://sdl.beuc.net/sdl.wiki/SDL_DisplayFormat

当然,你也应该确保析构函数之前SDL_Quit()叫,因为是正确的,虽然这不是什么导致你的访问冲突的时刻。

+0

嗯,我知道了,我之前尝试过这样做,但是我现在才意识到,我可能必须为渲染实体*创建参数,现在我已经完成了它的工作,那就是你所做的事情吗? – Cole 2012-02-18 17:02:54

+0

@Cole:I只是把'puppy'变成了一个指向在'main'的内部范围内声明的对象的指针,这需要我尽最大的努力才能使它工作,一个更好的解决方案可能是声明一个全局的'std :: set '所有要渲染的对象,然后它在渲染中通过它们中的每一个进行渲染。 – Gunslinger47 2012-02-18 21:54:28

3

这是一个全局变量:

Entity puppy("puppy.bmp"); 

它得到您的main()结束后销毁,所以你SDL_FreeSurfaceSDL_Quit()后调用。它有效吗?检查文件。

+0

所以问题可能是,析构函数被称为_too late_。让'puppy'变量也不能解决这个问题,因为析构函数会在main的末尾调用,仍然在'SDL_Quit()'之后。 'int main(){{... Entity puppy(“puppy.bmp”); ...} SDL_Quit(); }'应该可以工作(注意用于创建范围的额外大括号) – bames53 2012-02-18 00:54:22

+0

只要SDL初始化发生在{实体小狗...}之前 – marcinj 2012-02-18 00:57:19

+0

除非程序在运行几秒后崩溃,否则这将是一个好主意,不是当它退出循环时,我会将它添加到主帖子中,但是如果我使用gdb单步执行程序,小狗至少会被绘制一次,所以我不确定这个问题是什么。@ barnes53 – Cole 2012-02-18 01:35:40