Ошибка block type is valid

I been working in a new project but I encounter with a problem which I can’t see why fail.

When I perfom this line delete textY give me the error _Block_Type_Is_Valid (pHead->nBlockUse). So what am I doing wrong?

This is the source code:

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

So I think the problem is that when I destroy the object textY, the pointer to the TTF_Font is destroyed. But I’m not sure because when I add a object Text in the vector I use a copy-constructor so the different pointers got copy without problems.

I have a problem in my string class. After cin.get compiler display me this expression. Where did I go wrong?

//Source.cpp
#include <iostream>
#include <string>
#include "str.h"
using namespace std;


int main()
{
        str S1 = "Hello, world!";
        str S2 = "LOL";
        str S3 = S2;
        cout << S3.cstr() << endl;
        cout << S1.size() << ": " << S1.cstr() << endl;
        cin.get();
}



//str.h
#ifndef STR_H
#define STR_H

class str
{
public:
        str(const char* = "");
        ~str();
        void operator=(const char*);
        void operator=(str);
        const char* cstr();
        int size();
private:
        void newString(const char*);
        char* charPtr;
        int Size;
};

#endif




//str.cpp
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstring>
    using std::strlen;
    using std::strcpy;

    #include "str.h"

    str::str(const char* cstr)
    {
        newString(cstr);
    }
    str::~str()
    {
        delete[] charPtr;
    }
    const char* str::cstr()
    {
        return charPtr;
    }
    void str::newString(const char* cstr)
    {
        delete[] charPtr;
        Size = strlen(cstr);
        charPtr = new char[Size + 1];
        strcpy(charPtr, cstr);
    }
    void str::operator=(const char* cstr)
    {
        newString(cstr);
    }
    int str::size()
    {
        return Size;
    }

asked May 24, 2014 at 19:01

Orange Fox's user avatar

3

You didn’t obey the rule of three. You have user defined destructor and copy assignment operator, but you haven’t defined a copy constructor. The compiler helpfully</sarcasm> defined one for you.

On this line:

str S3 = S2;

You copy initialize S3. As you can see from the rules in the linked page:

If T is a class type and the type of other is cv-unqualified version of T or a class derived from T, the constructors of T are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.

The best matching constructor happens to be the str(const str&); which was added by the compier. The default copy constructor does not make a copy of the data pointed by the charPtr but just copies the pointer instead.

When S2 goes out of scope, after cin.get();, it’s destructor deletes S2.charPtr. Next, S3 is destroyed and it’s destructor tries to delete S3.charPtr which has the same value as S2.charPtr and is therefore already deleted. This has undefined behaviour. Quick googling suggests that _BLOCK_TYPE_IS_VALID assertion fails if heap pointer is invalid. I’m guessing it’s likely result of this undefined behaviour.

Solution: Implement the copy constructor str(const str&); so that copies don’t share data.

answered May 24, 2014 at 20:04

eerorika's user avatar

eerorikaeerorika

231k12 gold badges195 silver badges321 bronze badges

Цитата
Сообщение от IIARTEMII
Посмотреть сообщение

Что это за механизм такой, который реагирует на отсутствие виртуального деструктора, если по сути это приводит к утечке памяти, а не к программной ошибке (да, UB может привести к ошибке, а может и нет, но…)? Почему этот механизм себя проявляет только в MSVS?

Тут очень многое зависит от деталей реализации — от того, как сделаны
виртуальные таблицы в данном конкретном компиляторе и как устроен его
аллокатор памяти.

Приключения начинаются вот в этой строке:

C++
1
Base *ptr = new Der;

Если Base и Der — обычные классы, не отягощенные virtual-методами,
включая деструктор, то при касте указателя Der к Base его скалярное
значение сохранится. То есть, к примеру, если «new Der» вернет адрес
0xABCDE8, то и в ptr будет записано 0xABCDE8. В этом случае, когда
будет вызван «delete ptr», аллокатор получит все тот же адрес и
сможет корректно освободить занимаемую объектом Der память.
Хотя деструктор Der вызван не будет.

Предположим, Der унаследован не только от Base, но еще и от Megabase,
причем Megabase в списке наследования расположен раньше Base:

C++
1
class Der : public Megabase, public Base { ... };

В этом случае приведение указателя от Der к Base приведет к
изменению его скалярного значения.

Пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
struct Megabase
{
    virtual void somefunc() {}
};
 
struct Base
{
    virtual void anotherfunc() {}
};
 
struct Der : public Megabase, public Base {};
 
int main()
{
    using namespace std;
 
    Der  * pDer  = new Der();
    Base * pBase = pDer;
 
    cout << pDer  << endl;
    cout << pBase << endl;
 
    // delete pBase; // ???
 
    return 0;
}

Вот тут и начинаются глюки. «delete pBase» приведет к попытке
освобождения памяти по адресу 0x985043c, хотя при создании объекта
Der был возвращен адрес 0x9850438. Это равноценно тому, что в
delete передали адрес, который никогда не выделялся.
Кстати, возникновение ошибки в данном примере характерно не только
для MS Visual C++, можете проверить на любом компиляторе, который
есть под рукой.

Нечто похожее происходит и при виртуальном наследовании, так как
там «раскладка» классов в памяти заметно отличается от обычной,
хотя все это, повторюсь, очень compiler-specific:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
struct parent
{
    int a;
};
 
struct child : public virtual parent
{
    int b;
};
 
int main()
{
    using namespace std;
 
    child Child;
    cout << &Child.a << endl;
    cout << &Child.b << endl;
 
    return 0;
}

Неожиданно: a размещается в памяти после b.
При обычном (невиртуальном) наследовании все было бы наоборот.

И последний пример, снова с изменением скалярного значения указателя
при касте к базовому классу:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
struct parent
{
    int a;
};
 
struct child : public virtual parent
{
    int b;
};
 
int main()
{
    using namespace std;
 
    child  * pChild  = new child();
    parent * pParent = pChild;
 
    cout << pChild  << endl;
    cout << pParent << endl;
 
    // delete pParent; // ???
 
    return 0;
}

При полиморфном удалении объекта, когда базовый класс имеет виртуальный
деструктор, аллокатор всегда получает «правильный» адрес памяти для очистки,
так что проблем, описанных выше, не возникает.

  • Remove From My Forums
  • Question

  • Hi everybody.

    PRELIMINARY REMARKS: I know that allocating memory in a DLL function is not a good thing to do, because the user will (easily) forgot to delete it in the main program.

    By the way…

    I have a simple DLL where I have a function that allocate space for an int array and fill it with sequential numbers, than return the pointer to the first cell. The functin is declared as

    extern "C" __declspec(dllexport) int* GetArrayCreatePtr( int* size );
    

    The function definition is

    __declspec(dllexport) int* GetArrayCreatePtr( int* size )
    {
     int* arrayPtr = new int[ARRAY_SIZE];
     *size = ARRAY_SIZE;
    
     for(int i = 0; i < *size; i++)
      arrayPtr[i] = i;
    
     return arrayPtr;
    }
    

    (ARRAY_SIZE is defined in the header. For throughness’ sake, ARRAY_SIZE == 5)

    I have a console application that link the .lib of the dll, and call the function in this way

    int size;
    int* arrayPtr = GetArrayCreatePtr(&size);
    for(int i = 0; i < size; i++)
     printf("%dn",arrayPtr[i]);
    

    Everything works fine, but when I call

    in Release mode, nothing bad happens. When I call it in Debug mode I get this message

    Debug Assertion Failed

    Program: …

    File: dgbdel.cpp

    Line: 52

    Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

    Can someone tell me why this will happen and how to avoid it?

    Thanks in advance to everyone!

Answers

  • Hi Jesse.

    I’ve posted the solution of my problem in a previous post. I recall it here.

    About the «let it work» solution, declaring a FreeArray function as suggested by David Boyce UK fixed the problem. The definition is like this

    __declspec(dllexport) void FreeArray( int* arrayPtr )
    {
     delete [] arrayPtr;
    }
    

    I didn’t mark a «right answer» beacause I think there are a lot of really interesting answer, not just one. 

    By the way, I’ll mark this as the «answer to the problem».

    For anyone with similar problem, READ ALL POSTS!!! Lot of knowledge in!

    • Marked as answer by

      Tuesday, April 5, 2011 3:14 PM

Solution 1

Just use a std::string. That error means that you double deleted something, or something like that, a problem that you wouldn’t have if you didn’t manage your own memory. Your code is littered with memory leaks and other bugs that you won’t have with std::string.

Solution 2

From what I can see, the error has to do with the default ctor for Text. You take in a char* pointer, allocate space for the string, but don’t actually copy the text into str, but simply assign the pointer! You do it correct in the copy ctor though. Now, consider this example:

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

    ~Foo(){
        delete str;
    }

private:
    char* str;
};

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

C++03 (for backwards compatability…) allows literal strings ("hi") to bind to non-const char* pointers, as seen in this code. C++11 thankfully fixed that and this should actually no longer compile. Now, deleting a literal string obviously doesn’t work, as the string is placed in the read-only section of the .exe and as such isn’t deleteable. I guess this is where your error comes from, if you instantiate a Text object from a literal string.

Note that this also happens if you create it from a char[] created on the stack:

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

as the Foo will now try to delete a stack-object.

Another case where this might happen is if you double-delete an object:

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

Related videos on Youtube

warning illegal string offset: How do I fix? Hide PHP Warnings and Errors in WP

02 : 10

warning illegal string offset: How do I fix? Hide PHP Warnings and Errors in WP

Flutter Error || Error detected in pubspec.yaml || Expected a key while parsing a block mapping

02 : 31

Flutter Error || Error detected in pubspec.yaml || Expected a key while parsing a block mapping

Aleph Zero   Phân Tích Thảo Luận Điểm Mạnh và Điểm Yếu Của Blockchain Layer 1

01 : 09 : 18

Aleph Zero Phân Tích Thảo Luận Điểm Mạnh và Điểm Yếu Của Blockchain Layer 1

BÀI 8.  SỬA LỖI MATHTYPE

03 : 22

[Solved] A value of type 'Object' can't be assigned to a variable of type 'ProductType' | Flutter

00 : 38

[Solved] A value of type ‘Object’ can’t be assigned to a variable of type ‘ProductType’ | Flutter

Learn Flutter With Smrity

Error bounds for PFASST and related Block Spectral-Deferred-Correction algorithms

24 : 37

Error bounds for PFASST and related Block Spectral-Deferred-Correction algorithms

Flutter Tutorial - Fix Bottom Overflowed By Pixels [2021] When Keyboard Appears

04 : 26

Flutter Tutorial — Fix Bottom Overflowed By Pixels [2021] When Keyboard Appears

Flutter Custom Error Message - Flash Message

05 : 27

Flutter Custom Error Message — Flash Message

CREATE DIFFERENT WEB PAGES AND CONTROL BY JUST ONE BUTTON THAT CAN CHANGE FUTURES OF WEBSITES

04 : 38

CREATE DIFFERENT WEB PAGES AND CONTROL BY JUST ONE BUTTON THAT CAN CHANGE FUTURES OF WEBSITES

PreventDefault and StopPropagation

19 : 37

PreventDefault and StopPropagation

FLUTTER : Error detected in pubspec.ymail [Expected a key while parsing a block mapping]

00 : 52

FLUTTER : Error detected in pubspec.ymail [Expected a key while parsing a block mapping]

FDP client disables blocksmc anticheat

00 : 58

FDP client disables blocksmc anticheat

Modelling and Analysis of Block Type Machine Foundation by Finite Element Method using STAAD Pro.

29 : 39

Modelling and Analysis of Block Type Machine Foundation by Finite Element Method using STAAD Pro.

Error: The argument type 'Function?' can't be assigned to the parameter type 'void Function()?'

00 : 43

Error: The argument type ‘Function?’ can’t be assigned to the parameter type ‘void Function()?’

Hướng dẫn xử lý lỗi Plugin chữ ký số VNPT

04 : 37

Hướng dẫn xử lý lỗi Plugin chữ ký số VNPT

Cách khắc phục tất cả các lỗi thường gặp trên website wordpress

20 : 07

Cách khắc phục tất cả các lỗi thường gặp trên website wordpress

Talend Open Studio CSV Error : The Type Java Lang Object Cannot Be Resolved - Fixed

03 : 47

Talend Open Studio CSV Error : The Type Java Lang Object Cannot Be Resolved — Fixed

LearnToCode — الدارجة المغربية

PIDtoolbox 101 | How to Install, run, & solutions to common issues

05 : 58

PIDtoolbox 101 | How to Install, run, & solutions to common issues

How to Verify Blogger Site with Propeller ads | Propellerads  | Blogger Verified | Muhammad Faiq

07 : 11

How to Verify Blogger Site with Propeller ads | Propellerads | Blogger Verified | Muhammad Faiq

Tối ưu tốc độ Website WordPress với WP Rocket (92/100 điểm) và cách sửa lỗi nếu gặp phải

09 : 29

Tối ưu tốc độ Website WordPress với WP Rocket (92/100 điểm) và cách sửa lỗi nếu gặp phải

Comments

  • I been working in a new project but I encounter with a problem which I can’t see why fail.

    When I perfom this line delete textY give me the error _Block_Type_Is_Valid (pHead->nBlockUse). So what am I doing wrong?

    This is the source code:

    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
    

    So I think the problem is that when I destroy the object textY, the pointer to the TTF_Font is destroyed. But I’m not sure because when I add a object Text in the vector I use a copy-constructor so the different pointers got copy without problems.

  • Thanks for the help. I changed all the char* for std::string and work without problem. And expected it’s not problem if I ask, if there is a problem in use raw pointers in STL containers, I was thinking in use auto_ptr in some of them, and shared_ptr in other objects that it’s needed, it is really neccesary?

  • Thanks, I already solved the problem changing every char * to std::string, because it’s was causing a memory leak and other problems.

  • @oscar.rpr: You can’t use auto_ptr in Standard containers. This problem will be fixed in C++11, but in C++03, you will have to use shared_ptr— even if there’s only ever one reference.

  • Thanks for the help, so I will use shared_ptr instead of raw pointers in STL containers.

  • «a problem that you wouldn’t have if you didn’t manage your own memory» i hate this sentiment in a world of garbage collectors and reference counting that is more difficult to debug. sure string is a special case, but the right answer here is «a problem that you wouldn’t have if you managed your memory properly».

  • @jheriko: There’s a world of difference between garbage collectors and reference counting, and std::string/std::vector. Don’t manage your own memory manually. That’s just going to lead to infinity bugs.

  • yeah, std::string is a good thing for not having to manage character buffers. i don’t mean to lump all these things together — std::string (and other things like vector) are not automatic memory management, but reusable code that ‘just’ gets it right.

Recents

Related

Понравилась статья? Поделить с друзьями:
  • Ошибка bootmgr is missing что делать
  • Ошибка blinitializelibrary failed 0xc00000bb при запуске компьютера
  • Ошибка bootmgr is missing при установке
  • Ошибка blind spot syst function red 160
  • Ошибка bootmgr is missing windows 10