Hey,

I'm running into some issues with delete[]. I have these lines:

delete[] temp1;
delete[] temp2;

in a loop. temp1 and temp2 are pointers to std::strings. In the first iteration of the loop, temp1 and temp2 are both NULL pointers. The statements work fine. In the second iteration, the lines both still execute fine, but the the code immediately following them:

if(numAttributes > 1)
{
	temp1 = new std::string[numAttributes-1];
	temp2 = new std::string[numAttributes-1];
}

allocates arrays at temp1 and temp2.

By the third iteration, the two delete[] statements fail, and a dialog comes up saying Debug assertion failed. In the debugger, I saw that in the third iteration, temp1 and temp2 were labeled as "Bat Ptr" (which I'm assuming is bad pointer), rather than showing that they were NULL pointers ("0x000000" comes up).

Here is the bulk of the relevant code:

while(readAttributes)
		{
			numAttributes++;
			if(!ReadAttribute(atr_name,atr_value,tagtype,readAttributes))
				return 0;
			
			delete[] temp1;
			delete[] temp2;
			if(numAttributes > 1)
			{
				temp1 = new std::string[numAttributes-1];
				temp2 = new std::string[numAttributes-1];
			}
			for(int i = 0;i < numAttributes-1;i++)
			{
				temp1[i] = attributes[i];
				temp2[i] = atrValues[i];
			}
			delete[] attributes;
			delete[] atrValues;
			attributes = new std::string[numAttributes];
			atrValues = new std::string[numAttributes];
			for(int i = 0;i < (numAttributes-1);i++)
			{
				attributes[i] = temp1[i];
				atrValues[i] = temp2[i];
			}
			delete[] temp1;
			delete[] temp2;
	
			attributes[numAttributes-1] = atr_name;
			atrValues[numAttributes-1] = atr_value;
		}

So, what is the difference between NULL pointers and bad pointers, and why do the delete statements fail with the bad pointers?

From C++ Standard:

A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type. Two null pointer values of the same type shall compare equal.

So null pointer does not point to any live object but it's a special value differs from any other pointer values.

Bad pointer has not formal definition. Obviously, any pointer value which does not point to existing object is bad (you can't dereference it with * operator). Null pointer is too bad in that sense but it differs from others bad and good pointer values.

>So, what is the difference between NULL pointers and bad pointers
Null pointers have a predictable value while bad pointers do not.

>why do the delete statements fail with the bad pointers?
"Bad pointers" happen when you fail to initialize a pointer, manage to corrupt your memory, or try to free a pointer more than once. Step through your code and see if you can find where the change happens.

"Bad pointers" happen when you fail to initialize a pointer,

So:

int* pnNull = NULL;//null pointer
int* pnBad;//bad pointer?

manage to corrupt your memory,

How would that happen?

or try to free a pointer more than once.

Okay wait, so:

int* pnA = NULL;
delete pnA;//okay? still a null pointer? a bad pointer?
delete pnA;//is it a bad pointer now?
delete pnA;//will this cause the error I got?

//will it change if I throw a new in the mix?
pnA = new int;
*pnA = 5;
delete pnA;//okay? still a null pointer? a bad pointer?
delete pnA;//is it a bad pointer now?
delete pnA;//will this cause the error I got?

>int* pnBad;//bad pointer?
Yup.

>How would that happen?
If you allocate 10 bytes then copy 15 bytes to the pointer, you may overwrite private data used by the memory manager for handling dynamic memory.

>int* pnA = NULL;
>delete pnA;//okay? still a null pointer? a bad pointer?
Deleting a null pointer is always a no-op. It doesn't hurt anything.

>pnA = new int;
>*pnA = 5;
>delete pnA;//okay? still a null pointer? a bad pointer?
Fine here, but the only thing you can do with pnA at this point is reseat it to another address.

>delete pnA;//is it a bad pointer now?
Yes, now you've done some damage.

>pnA = new int;
>*pnA = 5;
>delete pnA;//okay? still a null pointer? a bad pointer?
Fine here, but the only thing you can do with pnA at this point is reseat it to another address.

So, at this point, pnA still contains the old address where there is now no data?

>delete pnA;//is it a bad pointer now?
Yes, now you've done some damage.

Okay, so now, we've attempted to delete data at an address, but no data exists. pnA is now bad?

So if we did a third delete, we would get an error, since this is the first time we tried to delete a bad pointer? Or was it already a bad pointer after the first delete, in which case the second delete would cause an issue?

Can we avoid this problem by adding a <pointer name> = NULL statement after every delete? Is there any harm/risk by doing this (other than potentially being unnecessary)?

>So, at this point, pnA still contains the old address where there is now no data?
pnA still contains the old address, but you don't own that memory anymore. Which means it could already be in use by another process.

>So if we did a third delete, we would get an error
It doesn't matter how many deletes you do, if it's more than one without an intervening reassignment, it's too late. And you might not get an error even if you do twenty deletes, you could just silently corrupt the results of another process.

>Can we avoid this problem by adding a <pointer name> = NULL
>statement after every delete?
That's actually a common guideline, but I don't believe strongly in it in this case because if your problem is multiple deletion, you're just covering up the real problem. Your code is doing something wrong, fix that.

I'm assuming the problem is that I'm deleting the temp variables at the top of the loop, which is unnecessary, since they're being deleted at the bottom, and they're null pointers at the first iteration. Since this loop is actually within another loop, I'm guessing it'd also be a good idea to set the variables to NULL before the loop. Would this work? (I'm away from my home computer right now, so I can't try it).

This article has been dead for over six months. Start a new discussion instead.