开发者

Can I delete[] a pointer that points into an allocated array, but not to the start of it?

开发者 https://www.devze.com 2023-03-14 12:13 出处:网络
I\'m wondering specifically about the following situation (which I discovered in some code I have to work with):

I'm wondering specifically about the following situation (which I discovered in some code I have to work with):

SomeClass *ar = new SomeClass[2];
ar++;
delete[] ar;

This code seems to be working fine - i.e. not crashing (win32, built with VS2005).

Is this "legal"? It certainly doesn't 开发者_Python百科feel right.


No, it is undefined to pass any address to delete which was not returned by new.
Here is the quote from the Standard.

§ 3.7.4.2-3

If a deallocation function terminates by throwing an exception, the behavior is undefined. The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_-t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.


No, not legal. You can only delete what you got back from new, and the exact same applies to new[] and delete[]


No it is not. You must call delete[] on the very same address (or pointer) that you received from new[]. You might just get lucky that it does not crash, but it definitely does not clear the memory appropriately.

References :

From http://www.cplusplus.com/doc/tutorial/dynamic/

The value passed as argument to delete must be either a pointer to a memory block
previously allocated with new, or a null pointer (in the case of a null pointer,
delete produces no effect).

From http://msdn.microsoft.com/en-us/library/h6227113.aspx

Using delete on a pointer to an object not allocated with new gives
unpredictable results. You can, however, use delete on a pointer with the
value 0. This provision means that, when new returns 0 on failure, deleting
the result of a failed new operation is harmless.


From standard docs,. 5.3.5.2 Delete,

... In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the behavior is undefined. ....

Also the sub-note 72) states that,

72)For non-zero-length arrays, this is the same as a pointer to the first element of the array created by that new-expression. Zero-length arrays do not have a first element.

And so yes, it is undefined.


The standard states that you can only delete what you allocated with new, but that doesn't explain why it crashes, or in this case, doesn't crash.

When you delete a pointer, you are putting it back in the heap to be used again in future allocations. The typical implementation gives you a pointer, with an int just before your pointer tracking the memory in the block (that's the typical malloc implementation). Like this, for a typical 32 bit system.

     p-4  size here
p-->     +--------+
         |  your  |
         |  block |

So if you point into the middle of the block, it's going to interpret the bytes just before it as a size, with potentially disasterous results. You were saved from seeing the crash by your tiny code example. Probably, you never tried to allocate after that point. If you try to allocate something after that, it will probably crash, because it will try to recycle some of the memory you just gave back.

The exact reason obviously depends on the implementation. This is just to explain one common way improper deletes can fail, not specifically verified for Visual Studio 2005.


It is not legal The fact that it does not crash does not mean it will not in other circumstances. It will surely crash if you enable verifier. And in any case it will not free your array. This is just the CRT / Windows letting your program not crash when it should


Can I delete[] a pointer that points into an allocated array, but not to the start of it?

If you don't pass the start of it, the delete won't get the extra info.

0

精彩评论

暂无评论...
验证码 换一张
取 消