_Block_Type_Is_Valid (pHead-> nBlockUse) Ошибка - PullRequest
18 голосов
/ 18 июня 2011

Я работал над новым проектом, но столкнулся с проблемой, которая не может понять, почему не получается.

Когда я выполняю эту строку, удаляю текст Y, выдается ошибка _Block_Type_Is_Valid (pHead-> nBlockUse). Так что я делаю не так?

Это исходный код:

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

Так что я думаю, что проблема в том, что когда я уничтожаю объект textY, указатель на TTF_Font уничтожается. Но я не уверен, потому что когда я добавляю объект Text в вектор, я использую конструктор копирования, чтобы разные указатели копировали без проблем.

Ответы [ 2 ]

11 голосов
/ 18 июня 2011

Просто используйте std::string. Эта ошибка означает, что вы дважды удалили что-то, или что-то в этом роде, проблему, которой у вас бы не было, если бы вы не управляли своей собственной памятью. Ваш код изобилует утечками памяти и другими ошибками, которых у вас не будет с std::string.

10 голосов
/ 18 июня 2011

Из того, что я вижу, ошибка связана с ctor по умолчанию для Text.Вы берете указатель char*, выделяете место для строки, но на самом деле не копируете text в str, а просто назначаете указатель!Вы делаете это правильно в копии ctor, хотя.Теперь рассмотрим этот пример:

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

    ~Foo(){
        delete str;
    }

private:
    char* str;
};

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

C ++ 03 (для обратной совместимости ...) позволяет литеральным строкам ("hi") связываться с неконстантными char* указателями, как видно из этогокод.C ++ 11, к счастью, исправил это, и это больше не должно компилироваться.Теперь удаление литеральной строки, очевидно, не работает, так как строка помещается в секцию .exe только для чтения и поэтому не может delete.Я предполагаю, что именно отсюда ваша ошибка, если вы создаете экземпляр Text объекта из буквальной строки.

Обратите внимание, что это также происходит, если вы создаете его из char[], созданного в стеке:

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

, поскольку Foo теперь будет пытаться delete объект стека.

Другой случай, когда это может произойти, если вы дважды удалите объект:

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