2011-06-18 11 views
18

He estado trabajando en un nuevo proyecto pero me encuentro con un problema que no puedo ver por qué falla._Block_Type_Is_Valid (pHead-> nBlockUse) Error

Cuando ejecuto esta línea borro textoY dame el error _Block_Type_Is_Valid (pHead-> nBlockUse). Entonces, ¿qué estoy haciendo mal?

Este es el código fuente:

Text.h

#ifndef TEXT_H 
#define TEXT_H 

typedef boost::shared_ptr<Font> FontPtr; 

class Text 
{ 
public: 

    Text(FontPtr font, char *text) 
    { 
     str = new char[35]; 
     this->font = font; str = text; 
    } 

    Text(const Text& cSource); 
    Text& operator=(const Text& cSource); 

    ~Text(); 
    . 
    . 
    . 
    . 

private: 
    FontPtr font; 
    char *str; 
    GLuint texture; 
    GLfloat pos_x, pos_y, width, height; 
}; 

#endif 

Text.cpp

Text::Text(const Text& cSource) 
{ 
    font = cSource.font; 
    texture = cSource.texture; 
    pos_x = cSource.pos_x; 
    pos_y = cSource.pos_y; 
    width = cSource.width; 
    height = cSource.height; 

    int sizeString = 35; 
    if (cSource.str) 
    { 
     str = new char[sizeString]; 
     strncpy(str, cSource.str, sizeString); 
    } 

    else 
    { 
     str = 0; 
    } 
} 

Text& Text::operator=(const Text& cSource) 
{ 
    delete[] str; 

    font = cSource.font; 
    texture = cSource.texture; 
    pos_x = cSource.pos_x; 
    pos_y = cSource.pos_y; 
    width = cSource.width; 
    height = cSource.height; 

    int sizeString = 35; 
    if (cSource.str) 
    { 
     str = new char[sizeString]; 
     strncpy(str, cSource.str, sizeString); 
    } 

    else 
    { 
     str = 0; 
    } 

    return *this; 
} 

Text::~Text() 
{ 
    delete[] str; 
} 

Font.h

#ifndef FONT_H 
#define FONT_H 

class Font 
{ 
public: 

    Font(TTF_Font *font, SDL_Color color) 
    { 
     this->font = font; this->color = color; 
    } 

    ~Font(); 
    . 
    . 
    . 

private: 
    TTF_Font *font; 
    SDL_Color color; 

}; 

#endif 

Font.cpp

Font::~Font() 
{ 
    TTF_CloseFont(font); 
} 

CGameApplication.cpp

. 
. 
. 
. 
void CGameApplication::initializeApplicationFonts() 
{ 
    TTF_Font* font; 
    SDL_Color color; 

    font = TTF_OpenFont("test.ttf", 15); 

    color.r = color.g = color.b = 255; 

    GApp->addFont(font, color); 

    Text *text = new Text(GApp->getFonts().at(0), " "); 
    text->setTexture(CTextM->textToGLTexture(GApp->getFonts().at(0), text)); 
    text->setPosX(20); text->setPosY(20); 

    GApp->addText(new Text(*text)); 

    Text *textY = new Text(GApp->getFonts().at(0), " "); 
    textY->setTexture(CTextM->textToGLTexture(GApp->getFonts().at(0), textY)); 
    textY->setPosX(80); textY->setPosY(20); 

    GApp->addText(new Text(*textY)); 
    delete textY;     //-----> This line crashes the program with that error 
} 
. 
. 
. 

GameApp.h

#ifndef GAMEAPP_H 
#define GAMEAPP_H 


class GameApp 
{ 
public: 
    GameApp(){ 
    } 

    //~GameApp(); 

    void addFont(TTF_Font *font, SDL_Color color) { 
     vFonts.push_back(FontPtr(new Font(font, color))); } 

    vector<FontPtr> getFonts() { return vFonts; } 

    void addText(Text *text) { 
     vTexts.push_back(new Text(*text));} 

private: 
    SDL_Surface *gameMainSurface; 
    vector<Image*> vImages; 
    std::vector<FontPtr> vFonts; 
    vector<Text*> vTexts; 
    vector<Tile*> vTiles; 
    Map *currentMap; 
}; 

#endif 

Así que creo que el pro blem es que cuando destruyo el objeto textY, el puntero al TTF_Font se destruye. Pero no estoy seguro porque cuando agrego un objeto Text en el vector utilizo un constructor de copia para que los diferentes punteros obtengan una copia sin problemas.

+0

¿Has caminado hasta la pila de llamadas para ver cuál era la última llamada en su código que provocó el error de depuración? (También, ¡Punteros sin procesar en contenedores STL! ¡Mis ojos! :)) –

+0

Sí, es solo una prueba mientras implemento punteros inteligentes en todos los contenedores STL. Voy a verificar la pila de llamadas. Gracias. –

Respuesta

11

Simplemente use un std::string. Ese error significa que eliminó por duplicado algo, o algo así, un problema que no tendría si no administrara su propia memoria. Su código está lleno de fugas de memoria y otros errores que no tendrá con std::string.

+0

Gracias por la ayuda. Cambié todos los caracteres * por std :: string y trabajo sin problemas. Y esperaba que no fuera problema si preguntaba, si hay un problema en el uso de punteros crudos en contenedores STL, estaba pensando en usar auto_ptr en algunos de ellos, y shared_ptr en otros objetos que se necesitan, ¿es realmente necesario? –

+0

@ oscar.rpr: No puede usar 'auto_ptr' en contenedores estándar. Este problema se solucionará en C++ 11, pero en C++ 03, tendrá que usar 'shared_ptr'- incluso si solo hay una referencia. – Puppy

+0

Gracias por la ayuda, así que usaré shared_ptr en lugar de punteros sin formato en contenedores STL. –

9

Por lo que puedo ver, el error tiene que ver con el ctor predeterminado para Text. Usted toma un puntero char*, asigna espacio para la cadena, pero no copia el text en str, ¡simplemente asigne el puntero! Sin embargo, lo corrige en la copiadora. Ahora, considere este ejemplo:

class Foo{ 
public: 
    Foo(char* text){ 
     str = text; 
    } 

    ~Foo(){ 
     delete str; 
    } 

private: 
    char* str; 
}; 

int main(){ 
    Foo f("hi"); 
} 

C++ 03 (por compatibilidad hacia atrás ...) permite que las cadenas literales ("hi") que se unen a no constante char* punteros, como se ve en este código. C++ 11 afortunadamente lo arregló y esto ya no debería compilarse. Ahora, borrar una cadena literal obviamente no funciona, ya que la cadena se coloca en la sección de solo lectura del archivo .exe y como tal no está habilitada para delete. Supongo que aquí es de donde proviene su error, si crea una instancia de un objeto Text a partir de una cadena literal.

Tenga en cuenta que esto también ocurre si lo crea a partir de una char[] creado en la pila:

char text[] = "hi"; 
Foo f(text); 

como el Foo tratará ahora de delete un objeto pila.

Otro caso en el que esto podría suceder es si hace doble elimina un objeto:

char* text = new char[3]; 
Foo f(text); 
delete text; 
+0

Gracias, ya he resuelto el problema cambiando cada char * a std :: string, porque está causando una pérdida de memoria y otros problemas. –

Cuestiones relacionadas