Android C++ new[] delete[] problems -> invalid HEAP etc

Started by
2 comments, last by Bregma 8 years, 6 months ago

I encountered this problem many times but now i don't know what to do

basically i create a set of object with new operator

like:



Items = new TFileItem[ Count ];

TFileItem is a strcuture


struct TFileItem
{
bool isDir;
AnsiString name;
TGLTexture thumbnail;

float x;
float y;
float w;
float h;

TFileItem()
{
isDir = false;
name = "";
}

~TFileItem()
{
	return;
	if (!isDir)
	thumbnail.~TGLTexture();
}

};

THEN THE MIGHTY HEAP CORRUPTION COMES.

whenever i try to


delete [] Items; 

i get this:

10-09 17:47:24.550: A/libc(26708): @@@ ABORTING: INVALID HEAP ADDRESS IN dlfree addr=0x53328f28
10-09 17:47:24.550: A/libc(26708): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 26723 (Thread-20999)
the worst thing is i actually have those Items created with Items = new TFileItem[ Count ];
and i just need to recreate the buff (with deleting old ones in memory)
heres the code (at the beggining theres that if (Items != NULL) then it deletes the array thats wheres the error coming from



void Update()
{
	ican = false;
	ProcessUpdate = false;

	if (Items != NULL)
	{
ALOG("DELETE VBUFF AND ITEM ARRAY");
delete [] Items;
ALOG("ITEMS DELETED");
delete [] VBUFF;
ALOG("DONE now null items");
Items = NULL;
ALOG("DELETE BUFFERS");
glDeleteBuffers(1, &item_vbuff);
ALOG("OK MAKE NEWE ARRAYS AND ENLIST");
	}


Count = s->Count + d->Count;
LastCount = Count;
Items = new TFileItem[ Count ];
VBUFF = new TFileItemVertex[ Count * 4 ];
ALOG("LIST dirs: found: "+IntToStr(d->Count) +" all items: "+IntToStr(Count));

int cnt = -1;
for (int i=0; i < d->Count; i++) //First enlist directories
{
	cnt = cnt + 1;
	Items[cnt].thumbnail = dir_thumbnail;
	Items[cnt].name = d->Strings[i];
	Items[cnt].isDir = true;
}

ALOG("LISTING FILES: items: "+IntToStr(s->Count));

for (int i=0; i < s->Count; i++) //secondly enlist files
{
	cnt = cnt + 1;
Items[cnt].thumbnail.LoadTGA(Directory+s->Strings[i]);
Items[cnt].name = s->Strings[i];
}


float sw = float(SCREEN_WIDTH);
float sh = float(SCREEN_HEIGHT);

float item_width = (width*sw) / float(row_items);

space_width = (item_width*0.2) /  float(row_items+1.0);
real_item_width = ((width*sw) - space_width*float(row_items+1.0) ) /  float(row_items);


for (int i=0; i < Count; i++)
{
int row = int( float(i) / float(row_items) );
max_row_counted = row;
int item_num = i % row_items;
		//number of spaces between items is always number_of_items per row + 1

PlaceItem(x*sw + space_width + (space_width+real_item_width)*float(item_num),
0.0, real_item_width, real_item_width, VBUFF, Items, i, sw, sh );
//((y+height)*sh - space_width) - float(row)*(space_width*3.0 + real_item_width)
}



rows_in_window = int((height*float(SCREEN_HEIGHT))  / (space_width*3.0 + real_item_width));

ALOG("space_width: "+FloatToStr(space_width));
ALOG("real_item_width: "+FloatToStr(real_item_width));
ALOG("height: "+FloatToStr(height));
ALOG("AVAIL ROWS IN WINDOW: "+IntToStr(rows_in_window));

glGenBuffers(1, &item_vbuff);
glBindBuffer(GL_ARRAY_BUFFER, item_vbuff);
glBufferData(GL_ARRAY_BUFFER, sizeof(TFileItemVertex) * 4 * Count, VBUFF, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

ALOG("VBUFF 0: "+POINT_TO_TEXT(VBUFF[0].v));
ALOG("VBUFF 1: "+POINT_TO_TEXT(VBUFF[1].v));
ALOG("VBUFF 2: "+POINT_TO_TEXT(VBUFF[2].v));
ALOG("VBUFF 3: "+POINT_TO_TEXT(VBUFF[3].v));
ican = true;
}

Log reports only:

DELETE VBUFF AND ITEM ARRAY

angry.png

TGLTexture is a class it stores unsigned char * pdata which is created by new too and unsigned int texture; <--for opengl but since new for that stores this in other part of memory and i do not delete it (since i block rendering queue with bool ican that shouldnt matter for opengl. so i dont know whats going on
Advertisement

The 0xdeadbaad address is reserved for native heap corruption. Something was messed up. There are lots of ways to mess up your native heap.

My first hunch is that somewhere in your code you've written past the end of your object. The system writes special markers before the beginning and after the end of your allocation. When you release the block it checks the markers to see that they are intact. If they aren't, you get the message you described. Find anywhere you may have gone over the ends of your memory buffer, because you probably are writing past the end of it.

My next hunch is that maybe you've got a double-delete. Your code certainly has some of the patterns for the bug.

I notice you did not nullify your pointers IMMEDIATELY after deleting what they point to. It looks like you eventually nullify Items but you never nullify VBUFF. A common practice is the next line following delete is ALWAYS an instruction to set the pointer to 0 or NULL or nullptr or whatever your coding standard requires.

The standard guarantees that calling delete on a null pointer is safe and does nothing, so your own duplicate test for that is somewhat unnecessary, other than revealing that you might be having some concerns over proper object lifetime management.

There are some other things that concern me about the block of code:

The most concerning thing for me is that your code is doing some potentially large allocations and releases mid-update. That leads to all kinds of issues. It fragments memory, takes time since memory allocation is always slow, and it is completely avoidable.

And to top it all off, you're doing it directly rather than using container classes that correctly handle the many error conditions in the language such as stack unwinding and exception safety guarantees.

You're violating the Single Responsibility Principle fairly badly, mixing image management, memory management, graphics rendering, object placement, and other concerns all in one method.

There are a few other things in there that are troubling, like your rapid consumption of OpenGL buffer names, but those aren't directly related to the bug you're posting about.

well i switched this to std::vector then found that when


	TFileItem neu;
	neu.thumbnail.LoadTGA(Directory+s->Strings[i]);
	neu.name = s->Strings[i];
	neu.isDir = true;
	Items.push_back(neu);

neu.thumbnail.LoadTGA(Directory+s->Strings); <-- did the same heap error so i cant just simply load texture there (maybe i should impolement = operator for this class) either way, when switching back to new/delete and commenting the texture class everything seems to work normally, i just wonder what the hell is going on here now, i think its becasue i try to delete with glDeleteTextures an object that was already deleted (nested destructor of TGLTexture)

Edit. Yes that was the shared texture deletion problem (i shouldnt delete it since its directory shared icon)

BTW i wasnt aware that delete [] some_pointer_to_class_array; calls the destructor of these classes, and its subclasses too (without calling destruction of subclasses in class destructor) :x


BTW i wasnt aware that delete [] some_pointer_to_class_array; calls the destructor of these classes, and its subclasses too (without calling destruction of subclasses in class destructor)

I would strongly urge you to master some of the basic basics of C++ before going any further.

Please note: constructing an object always calls a constructor, and destroying an object always calls its destructor. Always. Remember, copy constructors are constructors. Learn the rule of 3 (or 5 for the more advanced student).

Contained objects get constructed and destroyed when the object that holds them is constructed and destroyed. Always. If you explicitly invoke the destructor of a contained object in the destructor of the object that holds it, that object will be destroyed twice destroyed twice and you will probably corrupt your heap. It's called a double delete.

Unless you're an advanced C++ user writing very specialized code, you never invoke a destructor directly.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement