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
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
eerorikaeerorika
231k12 gold badges195 silver badges321 bronze badges
Сообщение от IIARTEMII
Что это за механизм такой, который реагирует на отсутствие виртуального деструктора, если по сути это приводит к утечке памяти, а не к программной ошибке (да, UB может привести к ошибке, а может и нет, но…)? Почему этот механизм себя проявляет только в MSVS?
Тут очень многое зависит от деталей реализации — от того, как сделаны
виртуальные таблицы в данном конкретном компиляторе и как устроен его
аллокатор памяти.
Приключения начинаются вот в этой строке:
C++ | ||
|
Если Base и Der — обычные классы, не отягощенные virtual-методами,
включая деструктор, то при касте указателя Der к Base его скалярное
значение сохранится. То есть, к примеру, если «new Der» вернет адрес
0xABCDE8, то и в ptr будет записано 0xABCDE8. В этом случае, когда
будет вызван «delete ptr», аллокатор получит все тот же адрес и
сможет корректно освободить занимаемую объектом Der память.
Хотя деструктор Der вызван не будет.
Предположим, Der унаследован не только от Base, но еще и от Megabase,
причем Megabase в списке наследования расположен раньше Base:
C++ | ||
|
В этом случае приведение указателя от Der к Base приведет к
изменению его скалярного значения.
Пример:
C++ | ||
|
Вот тут и начинаются глюки. «delete pBase» приведет к попытке
освобождения памяти по адресу 0x985043c, хотя при создании объекта
Der был возвращен адрес 0x9850438. Это равноценно тому, что в
delete передали адрес, который никогда не выделялся.
Кстати, возникновение ошибки в данном примере характерно не только
для MS Visual C++, можете проверить на любом компиляторе, который
есть под рукой.
Нечто похожее происходит и при виртуальном наследовании, так как
там «раскладка» классов в памяти заметно отличается от обычной,
хотя все это, повторюсь, очень compiler-specific:
C++ | ||
|
Неожиданно: a размещается в памяти после b.
При обычном (невиртуальном) наследовании все было бы наоборот.
И последний пример, снова с изменением скалярного значения указателя
при касте к базовому классу:
C++ | ||
|
При полиморфном удалении объекта, когда базовый класс имеет виртуальный
деструктор, аллокатор всегда получает «правильный» адрес памяти для очистки,
так что проблем, описанных выше, не возникает.
- 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
-
Marked as answer by
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 delete
able. 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
02 : 10
warning illegal string offset: How do I fix? Hide PHP Warnings and Errors in WP
02 : 31
Flutter Error || Error detected in pubspec.yaml || Expected a key while parsing a block mapping
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
03 : 22
00 : 38
[Solved] A value of type ‘Object’ can’t be assigned to a variable of type ‘ProductType’ | Flutter
Learn Flutter With Smrity
24 : 37
Error bounds for PFASST and related Block Spectral-Deferred-Correction algorithms
04 : 26
Flutter Tutorial — Fix Bottom Overflowed By Pixels [2021] When Keyboard Appears
05 : 27
Flutter Custom Error Message — Flash Message
04 : 38
CREATE DIFFERENT WEB PAGES AND CONTROL BY JUST ONE BUTTON THAT CAN CHANGE FUTURES OF WEBSITES
19 : 37
PreventDefault and StopPropagation
00 : 52
FLUTTER : Error detected in pubspec.ymail [Expected a key while parsing a block mapping]
00 : 58
FDP client disables blocksmc anticheat
29 : 39
Modelling and Analysis of Block Type Machine Foundation by Finite Element Method using STAAD Pro.
00 : 43
Error: The argument type ‘Function?’ can’t be assigned to the parameter type ‘void Function()?’
04 : 37
Hướng dẫn xử lý lỗi Plugin chữ ký số VNPT
20 : 07
Cách khắc phục tất cả các lỗi thường gặp trên website wordpress
03 : 47
Talend Open Studio CSV Error : The Type Java Lang Object Cannot Be Resolved — Fixed
LearnToCode — الدارجة المغربية
05 : 58
PIDtoolbox 101 | How to Install, run, & solutions to common issues
07 : 11
How to Verify Blogger Site with Propeller ads | Propellerads | Blogger Verified | Muhammad Faiq
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 useshared_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.