He estado trabajando en un nuevo proyecto, pero me encuentro con un problema que no puedo ver por qué fallar.

Cuando me perfom esta línea de eliminar textY me da el error _Block_Type_Is_Valid (pHead->nBlockUse). Entonces, ¿qué estoy haciendo mal?

Este es el código fuente:

De texto.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;
}

De la fuente.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 problema es que cuando me destruye el objeto textY, el puntero a la TTF_Font es destruido. Pero no estoy seguro porque al agregar un objeto de Texto en el vector puedo usar un constructor de copia para los diferentes punteros tengo copia sin problemas.

  • Hizo caminar hasta la pila de llamadas para ver la que fue la última llamada en el código que causó la depuración de fracaso? (También, Cruda Punteros en contenedores STL! Mis ojos! 🙂 )
  • Sí, es sólo una prueba, mientras que los puedo implementar punteros inteligentes en todos los contenedores STL. Voy a revisar la pila de llamadas. Gracias.
InformationsquelleAutor oscar.rpr | 2011-06-18

2 Comentarios

  1. 11

    Sólo tiene que utilizar un std::string. Ese error significa que el doble eliminado algo, o algo así, en un problema que no podría tener si usted no administra su propia memoria. Su código está llena de pérdidas de memoria y otros bichos que no tienen con std::string.

    • Gracias por la ayuda. He cambiado todos los char* para std::string y trabajar sin problema. Y la espera no es problema si me preguntan, si hay un problema en su uso en crudo, punteros en contenedores STL, yo estaba pensando en usar auto_ptr en algunos de ellos, y shared_ptr en otros objetos que necesita, es realmente necesario?
    • Usted no puede utilizar auto_ptr en los contenedores Estándar. Este problema será solucionado en C++11, pero en C++03, usted tendrá que usar shared_ptr– incluso si hay sólo una referencia.
    • Gracias por la ayuda, por lo que uso shared_ptr en lugar de raw punteros en contenedores STL.
    • «un problema que no podría tener si usted no administra su propia memoria» odio este sentimiento en un mundo de recolectores de basura de referencia y teniendo en cuenta que es más difícil de depurar. seguro de cadena es un caso especial, pero la respuesta correcta es «un problema que no podría tener si usted administra su memoria correctamente».
    • Hay un mundo de diferencia entre los recolectores de basura y el recuento de referencias, y std::string/std::vector. No administrar su propia memoria manualmente. Que sólo va a conducir a la infinidad de errores.
    • sí, std::string es una buena cosa para no tener que administrar el carácter de los buffers. no me refiero a combinar todas estas cosas juntas – std::string (y otras cosas como vector) no son automáticas, gestión de memoria, pero de código reutilizable que «sólo» se pone a la derecha.

  2. 10

    De lo que puedo ver, el error tiene que ver con el valor predeterminado cto r para Text. Tomar en un char* puntero, asignar espacio para la cadena, pero que en realidad no copiar el text en str, pero basta con asignar el puntero! Hacer lo correcto en la copia cto r de aunque. 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 (para compatibilidad con versiones anteriores…) permite a las cadenas literales ("hi") que se unen a la no-const char* punteros, como se ve en este código. C++11 afortunadamente fijo y que este debería en realidad no hay más tiempo de compilación. Ahora, la eliminación de un literal de cadena, obviamente, no funciona, ya que la cadena se coloca en la sección de sólo lectura de el .exe y, como tal, no es deletepoder. Supongo que esto es donde el error viene de que, si se crea la instancia de un Text objeto de un literal de cadena.

    Tenga en cuenta que esto también sucede si se cree a partir de un char[] crea en la pila:

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

    como el Foo ahora tratará de delete una pila de objetos.

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

    char* text = new char[3];
    Foo f(text);
    delete text;
    • Gracias, ya he solucionado el problema cambiando cada char * a std::string, porque estaba causando una pérdida de memoria y otros problemas.

Dejar respuesta

Please enter your comment!
Please enter your name here