C++ delete array memory without brackets still works? [duplicate] - c++

This question already has answers here:
Is delete[] equal to delete?
(6 answers)
how to properly delete a pointer to array
(6 answers)
How do I use arrays in C++?
(5 answers)
dynamically allocated string arrays failed to be deallocated
(2 answers)
Closed 9 years ago.
int* arr = new int[count];
delete arr;
Why does this work? I've checked and it actually frees the memory. From what I've read I need delete[] arr; otherwise it won't actually free all the memory.

The difference is not whether or not the allocated memory is properly freed - whether you use
delete
or
delete[]
the memory will still be properly deallocated.
The difference is whether or not the destructors will be properly invoked.
delete // will only invoke the destructor of the first element of the array.
delete[] // will invoke the destructor for *each* element of the array.
This has no practical effect for primitive types like int or float, but when you have an array of some class, the difference can be critical.

Now try it with filling the array with strings of 100 bytes each, and see if it still frees all the allocated memory...
It is undefined behaviour, and as always, sometimes UB will appear to work. In your case, you have no destructor for the objects in the memory, so there is no "further work", just free all the memory [1]. But if you have an object that has a destructor that does something useful, it (probably) won't get called.
You should ALWAYS use delete [] if you used new T[size]; to allocate. Don't mix the two, it's always wrong - just sometimes it HAPPENS to work [just like SOME sizes of spanners in inches works on mm nuts and vice versa - but it's still wrong to use a inches spanner set on metric nuts].
[1] Note that this may work for this particular compiler/C++ library combination. Compiling it with a different compiler, using a different C++ library, or compiling for a different OS may cause it to crash when you try the same thing.

delete and delete [] are actually different operators and to use the wrong one is always an error. The problem is that it often seems fine at the time, but the heap has ben corrupted and you are very likely to experience an apparently unrelated crash later.

Related

Difference between pointer to a new element and new array? [duplicate]

This question already has answers here:
How could pairing new[] with delete possibly lead to memory leak only?
(10 answers)
Closed 3 years ago.
In C++ is there any difference between the pointers p and q in the below code?
int* p = new int;
int* q = new int[5];
I understand that one allots new memory for a single int and the second allots memory for an array of 5 ints, but fundamentally is there any difference between a pointer pointing to a single int and one pointing to an array of ints?
I got this doubt because I read that one must use delete[] q to free up memory pointed to by q but just delete p for the single int pointed to by p.
What would happen if I used delete q?
The pointers themselves are completely indistinguishable. That's why you must remember to match new/delete and new[]/delete[].
Mismatching them triggers undefined behaviour.
When using new [] some c++ implementations will track the size of the allocation of the array in the address before the pointer returned. This is an implementation detail not defined by the standard.
The following answer describes this possible implementation in a little more detail: How could pairing new[] with delete possibly lead to memory leak only?
You must always match new with delete and new [] with delete []. It is Undefined Behavior to mix these.
In C++ is there any difference between the pointers p and q in the below code?
There is no visible difference between the pointers, but there certainly is one, and it is important. One is a pointer to an integer, the other is a pointer to an integer, which is also the first element in an array of a given size.
Unluckily, given only the pointer, you have no way of telling.
What would happen if I used delete q?
Probably nothing, but possibly a lot.
First of all, calling delete instead of delete[] will call the destructor exactly once, on the first element of the array, rather than on every element as it should. Now, the destructor for a trivial type like int doesn't do anything, so... as far as that goes, there is no real difference. There is, however, a huge difference for not-so-trivial types where the destructor (or chain of destructors) actually does something.
Second, you are interfering with proper deallocation of the underlying raw memory block. This can (and sometimes does) cause a hard crash. It might even cause a crash which occurs at a later time, in an unrelated, innocent piece of code, due to corruption earlier. Try and debug that.
Or, you might get a silent memory leak, it depends on the implementation and sometimes even on your "luck" in the particular case (e.g. hit a page boundary or not).
Because, well, allocating and freeing an array and allocating and freeing a single element just isn't the same thing. They are (usually) implemented slightly differently, and while the implementation may be able to cope with mismatched new/delete, that isn't guaranteed. You might get different behavior in the debugger compared to normal exection, too, whatever, anything.
Calling the wrong form of delete means invoking undefined behavior. Which basically means anything can happen. That includes "nothing" as well as "problem which is impossible to debug". It also includes the possibility of the compiler optimizing maliciously or just stripping out the entire surrounding function, or assuming a certain condition to be always-true. Which can lead to very nasty surprises on which you spend days and days trying to figure out what's going on.

Why two operators for deleting dynamically allocated memory? [duplicate]

This question already has answers here:
Why do we even need the "delete[]" operator?
(7 answers)
Closed 8 years ago.
This question may sound a bit weird, but I never entirely got why do we need to have 2 different syntax for deleting dynamically allocated memory in C++?
For example,
int *p = new int[10];
delete[] p; // why not just delete p;?
In plain old C, you just use the free function to release the memory allocated for a pointer, regardless of the number of elements allocated. Of course, C++ is a bit more complicated, as it allows for class types, which invoke their destructor etc. However, I see no impediment in using a single syntax for deleting dynamically allocated memory in C++.
Is there any fundamental reason why it was decided to use 2 versions, delete and delete[]?
More than that, most compilers do not even warn you if you use delete instead of delete[], and this creates undefined behaviour.
The underlying reason is that arrays don't have destructors. But arrays are still objects. Therefore, when arrays are allocated dynamically, they require special treatment. A pointer to an object is indistinguishable from a pointer to the first element of an array, so you need a special language construct to indicate that the pointer points into an array, and that multiple array elements need to have their destructors called.
An expression with the delete[] operator, first calls the appropriate
destructors for each element in the array (if these are of a class
type), and then calls an array deallocation function.
From here
The language allows you to overload the underlying allocation and deallocation functions. You might want to do this differently for single objects and for arrays; having two different operators allows you to do that.

Logic in C++'s delete and delete[] [duplicate]

This question already has answers here:
Is delete[] equal to delete?
(6 answers)
Closed 9 years ago.
In C, free() is used to release the memory, say free(ptr). As I understand, extra memory is allocated before ptr in the library code to store the block size information. After free() is called, the whole block is tracked and then released.
In C++, there are two forms of new and delete. One is for array. If new[] is used, delete[] should be used. For example,
int ptr = new [10];
delete [] ptr;
Question 1: can I use delete ptr here? If that is OK, what if delete ptr + 2?
Question 2: If delete[] has to be used to match new[], why do we need two forms of delete? Just one form, say delete, would be enough.
Thanks for all the suggestions!
Thank Mgetz. Question 2 should be: why c++ standard proposed both delete [] and delete if there is only one correct form at any situation?
Q1: You can use delete, but it is wrong.
This will usually "work" insofar as it will correctly free the allocated memory, but it will not call destructors properly. For trivial types, you will often not see any difference, but that doesn't mean it isn't wrong anyway. In any case it is undefined behavior which you should avoid if you can (invoking UB forfeits any guarantees that your code will work, it might of course still work, but you can never be 100% sure).
Deleting ptr+2 is also undefined behavior and will almost certainly not "work", not even a little. Usually, this will simply result in a program crash.
Q2: You need the two because they mean different things. One means "delete this pointer-to-single-object" whereas the other means "delete this pointer-to-array-of-objects".
Obviously, the compiler needs to generate different code for those different things.
You need the two forms because, unlike malloc and free, new and delete do more than just allocate and deallocate memory; they also construct and destruct the object(s) respectively.
new and delete deal with scalar objects, while new[] and delete[] deal with arrays of objects.
When you call new T[n], it'll allocate enough memory for n copies of T, and then construct n instances within the allocated memory. Similarly, calling delete[] will cause destruction of those n instances followed by deallocation.
Obviously, since you do not pass n to delete[] that information is being stashed away somewhere by the implementation, but the standard doesn't require an implementation to destroy all n objects if you call delete instead. The implementation could just destroy the first object, it might behave correctly and destroy all n objects or it might cause demons to fly out of your nose.
Simply put, it's undefined behavior, there's no telling what'll happen, it's best imperative you avoid it.

how are `delete[] obj` and `delete obj` implemented at compiler level [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why [] is used in delete ( delete [] ) to free dynamically allocated array?
Why does C++ still have a delete[] AND a delete operator?
I'm wondering what's their difference and I know the obvious answer some might say, that one is to delete an array and the other is to delete a single object but I'm wondering why should there be two different deletion methods for these two operations? I mean delete is basically implemented using C free method which doesn't care if the pointer is actually pointing toward an array or a single object. The only reason I can think of is two be able to know if it's an array and call destructor for each cell instead of only the first object but that wouldn't also be possible since compiler can not guess the length of array just looking at it's pointer. By the way though it's said to invoke undefined behavior to call delete for memory allocated with new[] I can't imagine anything that could possibly go wrong.
As you have discovered the compiler needs to know the length of an array (at least for non-trivial types) to be able to call destructors for each element. For this new[] typically allocates some extra bytes to record the element count and returns a pointer to the end of this bookkeeping area.
When you use delete[] the compiler will look at the memory before the array to find the count and adjust the pointer, so that the originally allocated block is freed.
If you use delete to destroy a dynamically allocated array, destructors for elements (except the first) won't be called and typically this will end up attempting to free a pointer that doesn't point to the beginning of an allocated block, which may corrupt the heap.
but that wouldn't also be possible since compiler can not guess the
length of array just looking at it's pointer
That's not really true. The compiler itself doesn't need to guess anything, but it does decide which function to call to free the memory based on the operator it sees. There is a separate function dedicated to releasing arrays, and this function does indeed know the length of the array to be freed so it can appropriately call destructors.
It knows the length of the array because typically new[] allocates memory that includes the array length (since this is known on allocation) and returns a pointer to just the "usable" memory allocated. When delete[] is called it knows how to access this memory based on the pointer to the usable part of the array that was given.
When you allocate memory using new[], the compiler not only needs to construct each element, it also needs to keep track of how many elements have been allocated. This is needed for delete[] to work correctly.
Since new and delete operate on scalars, they don't need to do that, and could save on a little bit of overhead.
There is absolutely no requirement for new to be compatible with delete[] and vice versa. Mixing the two is undefined behaviour.

How does delete[] keep track of the number of elements? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does delete[] “know” the size of the operand array?
How does the delete in C++ know how many memory locations to delete
I know it's a rather simple question but I a not sure about the difference (if any) between this lines :
double * a = new double[100];
delete[] a;
delete a;
free ((void*)a);
First off, would all of these calls (used each without the others) work the same way and free sizeof(double)*100 bytes?
Which lead me to the 2nd question, how does the program keep track of the size of the allocated memory? For instance if I send my a pointer to a function, then delete[] this pointer from within my function, would I also free the same amount of memory?
Thanks
The difference, oversimplified, is this:
delete[] a;
Is correct. All others are incorrect, and will exhibit Undefined Behavior.
Now, in reality, on all the compilers I use daily, delete a; will do the right thing every time. But you should still not do it. Undefined Behavior is never correct.
The free call will also probably do the right thing in the real world, but only because the thing you're freeing doesn't have a non-default destructor. If you tried to free something that was a class with a destructor, for example, it definitely wouldn't work -- the destructor would never be called.
That's one of the big differences (not the only difference) between new/delete and malloc/free -- the former call the constructors and destructors, while the latter meerly allocate and dealocate space.
Incorporating something #Rob said in his now-deleted post:
The simple rule is this: every new[] requires exactly one delete[].
Every new requires exactly one delete. malloc requires free. No
mix-and-match is allowed.
As to the question of how delete[] knows how many elements to delete, please see this response to a previous duplicate question.
Someone correct me, if I'm wrong, but as far as I understand, you use delete when you previously allocated memory with new and delete[] after using new Type[]. And free is used when you have allocated memory using malloc.
See c++ reference on delete and free.
Regarding the array of doubles, the result of all forms is the same -- all the allocated memory is returned to the system. The difference in calling free vs. delete vs. delete[] is:
free only releases the memory (the size of memory allocated for a was stored by memory manager when calling new)
delete calls the destructor of allocated object before releasing the memory
delete[] calls the destructor of each element in the array before releasing the memory
The difference is important if destructor of the allocated object contains cleanup code which releases other memory or system resource such as file or socket descriptor allocated during the lifetime of an object.
It is a good habit in C++ to allways use deleteon single instances and delete[] on array of objects/primitives regardless of the content of destructor.