views:

289

answers:

2

Hi, I am wondering about the delete[] operator in C++. (I am using Visual Studio 2005).

I have an unmanaged DLL that is being called by a managed DLL. When I close this program after performing a few tasks while debugging, I am getting many (thousands?) of memory leaks, mostly 24 bytes - 44 bytes in size.. I suspect it might be due to a certain unmanaged DLL I have.

Anyway, from what I understand, if I have the following code:

char* pointer = new char[500]
/* some operations... */
delete[] pointer;

Then all the memory for it is freed up correctly, am I right?

What happens when I have the following code:

char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
    *pointerIt = 0;
    pointerIt++;
}

delete[] pointer;

The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?

Anyway, what happens now if I do this:

char* pointerFirstPosition = new char[500];
char* pointerIt = pointerFirstPosition;

for (int i = 0; i < 250; i++){ // only iterate halfway
    *pointerIt = 0;
    pointerIt++;
}

delete[] pointerIt; // delete the pointer iterator...

Will this code delete the memory block pointed to by pointerIt up to pointerIt +500? or will it delete the memory block pointed to by pointerFirstPos to pointerFirstPos +500?

Could this result in a memory leak?

Sorry for the long winded message, I'm trying to get my message across clearly.

Thanks,

kreb

+3  A: 

First question set:

char* pointer = new char[500] 
/* some operations... */ 
delete[] pointer;

Then all the memory for it is freed up correctly, am I right?

right.

Second question set:

char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
    *pointerIt = 0;
    pointerIt++;
}

delete[] pointer;

The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?

The memory pointer holds an address to is fully delted yes. Both pointer and pointerIt hold an address to invalid memory. Each pointer is simply a variable, and every variable is independent. So both store their own address independent of each other. The dereference operator * will simply give you the variable at that address. The variable at that address is a different variable than the pointer variable.

Third question set:

You should be deleting only the address that was allocated, the whole array. You'll have undefined results if you try to delete a partial array. Could it result in a memory leak? Possibly, could it result in a crash? Possibly, could it result in ....? Possibly.

So only delete what you allocate. If you allocate an array then you delete with delete[] if you delete a type that is not an array you delete with delete.

Here is an eample of something that is fine just for clarity:

char* pointer = new char[500];
char* pointerIt = pointer;
//This is fine because you are deleting the same address:
delete[] pointerIt;
//The memory that both variables point to is freed, do not try to free again
Brian R. Bondy
It is undefined to `delete` or `delete[]` anything other than what was created using `new` or `new[]`.
GMan
Thanks, that was what I suspected. But say, for example in the third question set, I set pointerIt = pointerFirstPosition, then delete[] pointerIt, is this still undefined? I'm working with someone else's OLD code, he already left the company, and I'm trying to figure out if this is the reason for the memory leaks..
krebstar
Just for kicks I tested this out under g++ 4.4.1 -- basically the same code as what you've got in your third code sample except with `pointerIt` moved halfway down the array. Calling `delete[]` on `pointerIt` invalidates `pointer`, but obviously this behaviour cannot be expected from every compiler if the behaviour is undefined.
Meredith L. Patterson
@krebstar: I think I covered that in section #3.
Brian R. Bondy
Thanks Meredith, I'm not so much concerned about invalidating pointer, but as to whether the memory is actually freed. I guess my question is, does running the third set cause a leak of 250 bytes (the 250 byte locations prior to the last position of pointerIt)? Does it corrupt the 250 memory locations after pointerFirstPos+500 by freeing memory that it didn't allocate? Thanks :)
krebstar
Ok thanks brian :) I guess since it is undefined behavior.. The answer is.. "Possibly" :) Thanks for the help! :)
krebstar
@krebstar: Yes exactly, np.
Brian R. Bondy
@krebstar: I just ran the sample code through valgrind and realised that it's dumping core before I thought it was -- the delete[] on pointerIt is invalid because it won't *let* me deallocate an address that wasn't allocated. I guess VC++ plays more fast and loose than g++ in this regard. Anyway, valgrind should be informative. Good luck!
Meredith L. Patterson
@Meredith wow thanks :) I don't know how to use Valgrind yet, and I don't have a linux dev machine at the moment.. :) Thanks!
krebstar
A: 

check out boost::shared_ptr or boost::scoped_ptr and NEVER worry about this again. This gives you a static & reference counted way to manage your memory.

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm

George
If I do this I'll have to modify so many projects.. :( Something my manager can't justify.
krebstar
For future code, then. Also, use `std::vector` and kin. No manually memory allocations **ever**.
GMan
Ok, thanks guys, very helpful :)
krebstar
@George: Note that the code would require `shared_array`. (Or, indeed, `std::vector`.)
sbi
@krebstar that's a different question.char* pointer = new char[500]you could just use std::stringif you're doing i/o processing, use streams'something my manager can't justify' - just do it :)
George
@george well actually i'm not dealing with strings here, just byte-sized data actually.. Thanks anyway :)
krebstar
@krebstar Then streams are the way to go. IMHO if you're going to code in C++, you might as well use the features.
George