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?

5
  • 5
    operator delete[] of course. int[1] is not int. Compiler smart enough won't convert the statement. Commented Jul 12, 2013 at 7: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. Commented Jul 12, 2013 at 7: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)? Commented Jul 12, 2013 at 7:45
  • 3
    It's probably worth pointing out, too, that there are practically no known cases where you should use new[]. Commented Jul 12, 2013 at 7: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. Commented Jul 12, 2013 at 8:04

6 Answers 6

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.

3
  • Can you please refer me back to the standards?
    – Abhijit
    Commented Jul 12, 2013 at 7: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
    Commented Jul 12, 2013 at 7: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
    Commented Jul 12, 2013 at 7: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.

5
  • 2
    IIRC, new[0] wasn't allowed.
    – Qaz
    Commented Jul 12, 2013 at 7: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.
    – Qaz
    Commented Jul 12, 2013 at 7: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
    Commented Jul 12, 2013 at 7:43
  • 2
    You can allocate an array of size zero
    – CB Bailey
    Commented Jul 12, 2013 at 7:46
  • 1
    It seems to work fine in any form for me. I really think it was stack-allocated arrays I was thinking of.
    – Qaz
    Commented Jul 12, 2013 at 7: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.

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.

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.

1
  • 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
    Commented Feb 22, 2017 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.