8

If we allocate an object of size 1 as below

int *arr = new int[1];

Should we delete the object using operator delete[] or operator delete?

The reason I am concerned is if the compiler would be smart enough to convert the statement as a single element allocation int *arr = new int which would cause calling operator delete[] UB.

User Case:

I have a pointer, which I would end up allocation in a varied ways but would finally like to get it deleted. So was wondering, for single element allocation, if I consistently use int *arr = new int[1] can I consistently and safely use operator delete[]

Note

Can you please refer me back to the standards to support your answer?

Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • 5
    `operator delete[]` of course. `int[1]` is not `int`. Compiler *smart enough* won't convert the statement. – johnchen902 Jul 12 '13 at 07:25
  • 2
    It is the same place in the standard that tells you to call `delete[]` after `new[]`. there is no special case for size 1. – juanchopanza Jul 12 '13 at 07:35
  • 1
    *If* the compiler *was* smart enough to do that (though changing one type into another hasn't anything to do with smartness at all), it would have to inform you of this change or this change would have to be specified in the standard and in this case it wouldn't be smartness either, but mandatory. If it was silently behind the back then that compiler wasn't smart but *intentionally evil*. No need for any standard document apart form common sense, an `int` just *is not the same* as an `int[1]`. Is a one-element array still an array (hint: answer hidden in this comment)? – Christian Rau Jul 12 '13 at 07:45
  • 3
    It's probably worth pointing out, too, that there are practically no known cases where you should use `new[]`. – James Kanze Jul 12 '13 at 07:52
  • 2
    This is a silly question. It doesn't matter how "smart" a compiler is, it cannot introduce undefined behaviour (1.9 [intro.execution] p5) and require the programmer to alter source code that is correct, and you already know that using `delete[]` with `new[]` is correct and required by the standard. Such an optimisation by a "smart" compiler would mean the program works on one compiler and not another. That way madness lies. – Jonathan Wakely Jul 12 '13 at 08:04

6 Answers6

13

You must use delete[] and not delete. The compiler is not allowed to change new int[1] to new int.

(As int is a POD type it's quite possible that new int and new int[1] do exactly the same thing under the covers, but if this is the case then delete[] on and int* and delete on an int* will also do exactly the same thing.)

ISO/IEC 14882:2011 5.3.5 [expr.delete] / 2:

In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined.

As int[1] is an array object, if you try and delete it with delete and not delete[], the behavior is undefined.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • Can you please refer me back to the standards? – Abhijit Jul 12 '13 at 07:27
  • @Abhijit: It's not stated in the standard, so I can't give you a section number, but for the same reason it's not allowed. – MSalters Jul 12 '13 at 07:28
  • In addition to the *delete-expression* restrictions, there are restrictions to the Standard Library deallocation function: "Otherwise, the behavior is undefined if the value supplied to `operator delete(void*)` in the standard library is not 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 [...]" (+ the same for the array (de)alloc) [basic.stc.dynamic.deallocation]/3 – dyp Jul 12 '13 at 07:38
6

The rule is quite simple:

  1. always balance a new with a delete
  2. always balance a new[] with a delete[]

otherwise you get undefined behaviour.

There are no exceptions; even new[1] must be balanced with a delete[], and new[0] must be deleted as the compiler can still reserve storage.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 2
    IIRC, `new[0]` wasn't allowed. – chris Jul 12 '13 at 07:34
  • 1
    If I recall correctly. I don't see anything from a quick standard sweep, though, so perhaps I remembered wrong or ran into a faulty compiler error, or perhaps I was thinking of a normal array. – chris Jul 12 '13 at 07:36
  • I remember allocating new[0] by mistake a few years ago. But that compiler didn't even scope the for loop correctly! I'm upgrading my compiler today (to C++11): will re-check. – Bathsheba Jul 12 '13 at 07:43
  • 2
    [You can allocate an array of size zero](http://stackoverflow.com/questions/6180012/array-with-size-0) – CB Bailey Jul 12 '13 at 07:46
  • 1
    It seems to work fine in any form for me. I really think it was stack-allocated arrays I was thinking of. – chris Jul 12 '13 at 07:46
2

Should we delete the object using operator delete[] or operator delete?

operator delete[]. You have allocated an array of ints, so there's no other option for correctly deallocating it. Using operator delete would invoke undefined behavior.

2

You must use delete[].

C++11 5.3.5 Delete

::opt delete cast-expression

::opt delete [ ] cast-expression

The first alternative is for non-array objects, and the second is for arrays.

An array holding one element is still an array.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
1
int *arr = new int[1];

Since you use [] for allocation, you need to use [] for deleteas well.

Memory leaks

The objects created by new expressions (objects with dynamic storage duration) persist until the pointer returned by the new expression is used in a matching delete-expression.

So you should use delete[] for releasing the memory or else you get undefined behaviour.

And (incase), if the complier is smart enough to take int * arr = new int[1] as int, It must be smart enough to take delete[] arr on arr as delete arr. However, there is nothing for delete to differentiate between the arr from int*arr = new int[1] and int*arr = new int. The [] in delete is going to indicate it.

Suvarna Pattayil
  • 5,136
  • 5
  • 32
  • 59
0

No its not safe, it may leads to some unwanted situations.
For example,It is possible in a memory to have some data (int/char/float...) next to the location where your pointer points to. At that time if you used delete [] then it may try to delete that data too if it is an integer,for other data types it leads to unexpected errors.

Example:

int *ptr = new int;
int a = 20;
char c = 'e';
*ptr = 10;
delete [] ptr;

There is a possibility the c and a variables may store next to the location where the pointer ptr points to, If a is stored next to it, then it deletes "a" also, if the other data types are present, leads to unexpected runtime results.

So it's advised to use delete[] only for the deletion of memory allocated using new datatype[].Hope this is useful.

Suvarna Pattayil
  • 5,136
  • 5
  • 32
  • 59
Raju
  • 1,149
  • 1
  • 6
  • 19
  • How would stack allocated variables end up next to heap allocated ones? How did you come up with that "possibility"? Please refrain from writing just for the sake of writing. – Radu C Feb 22 '17 at 22:11