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.
Related
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.
I'm facing some conceptual issues in dynamic memory allocation. Firstly if I write the following piece of code
int *p = NULL;
delete p;
why I get no error? I'm trying to delete the pointer (on the stack) which is not pointing to anything. Also if I write the following statement
int *p = new int;
p = NULL;
delete p;
I again get no compile or runt-time error. Why ?
Moving on if I write the following code I get a runtime error
int *p = new int;
p = NULL;
delete p;
delete p;
Why? And if I write the following code, I get no error
int *p = NULL;
delete p;
delete p;
Why ? Can anyone explain conceptually the reasons behind this ?
I assume that in your third example you meant to write
int *p = new int;
delete p;
delete p;
Formally this causes undefined behaviour, which means that anything could happen. In practice you are probably using a memory allocator that checks whether the pointer you are deleting points within its free memory pool.
Others already pointed out that deleting a null pointer doesn't cause an error by definition, so it doesn't matter how many times you do it.
Passing a null pointer to the delete operator is a no-op. The standard says so:
5.3.5/2
In either alternative [delete and delete[]], if the value of the operand of delete is the null pointer the operation has no effect.
Consider an object that owns a pointer to another object. Usually, when the destructor of the owning object is run, it would clean up the memory for the owned object by deleting it. But in the case where the owned object could also be null, what would we do to clean up the memory? One option would be to wrap every single delete in an "if (X) delete x" kind of wrapper. But that's horrendously noisy, for no real added benefit. Therefore, the delete operator does it for you.
"I'm trying to delete the pointer (on the stack) which is not pointing to anything."
This is not true. You cannot delete from stack. With delete you delete memory blocks on the heap whose adress is stored in a pointer. The pointer itself is a stack variable.
In every case you are only deleting a nullpointer, which by definition is always "safe" because it is a no-op (the C++ standard explicitly says so).
In your second and third example, you are reassigning a new value (the nullpointer) to the pointer before deleting it, which means that you are leaking the previously allocated integer. This is something that should not normally happen (in this case, you won't die from leaking a single integer, but it's not a good thing).
The double deletion in the third and fourth examples are normally serious programming errors, but they are "harmless" in your example because the deleted pointer is the nullpointer (so it's a no-op).
Going a bit O/T:
Note that I have put "safe" and "harmless" in quotes above for good reason. I personally disagree with Mr. Stroustrup's design decision here.
Making the deletion of a nullpointer a "harmless no-op" is actually not a very good idea, even if the intent was probably good. Mr. Stroustrup even goes further by allowing delete to set the pointer to the nullponter and saying he wished that implementations actually did that (luckily no implementation that I know does!).
In my opinion, every object that was allocated should be deleted exactly once, none less and not more often.
When and how often a well-behaved, non-broken program may (and must) delete a pointer is exactly defined, it is not a random unknown thing. Deletion must happen exactly once, and the program must be exactly aware of it because it must be certain whether or not an object is valid (because it's illegal to use the object if it isn't valid!).
Setting a pointer to the nullpointer after deleting the object will cause a fault when dereferencing the deleted object afterwards (this is a good thing), but it does not protect from double deletion. Instead, it hides this serious programming error, ignoring it silently.
If a program deletes a pointer twice, then the program logic is broken, it is not working properly. This is not something that can be ignored, it must be fixed. Therefore, such a program should crash. Allocators usually detect double deletion, but by resetting a pointer to the nullpointer, one has effectively disabled this detection mechanism.
If one chooses to reset a pointer after deleting it, one should (in my opinion) set it to an invalid non-nullpointer value, for example (T*)1 or (T*)-1. This will guarantee that both dereferencing and deleting the pointer will crash on the first occasion.
Nobody likes to see program crashes. But crashing early and crashing at the first occasion is a good thing compared to an incorrect program logic continuing for an indeterminate time, and possibly crashing or silently corrupting data at a random occasion.
I think that if you are trying to deleate the pointer, you are actually deleting the place in tye memory of the object that the pointer points. You can do it using reference:
int *p = NULL;
delete &p;
The inner implementation is transparent to us programmers. As you see, delete a NULL pointer may be harmless, but generally you should avoid this. You may have seen words like 'please do not re-delete dynamic pointers'
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.
Someone on IRC claimed that, although allocating with new[] and deleting with delete (not delete[]) is UB, on Linux platforms (no further details about the OS) it would be safe.
Is this true? Is it guaranteed? Is it to do with something in POSIX that specifies that dynamically-allocated blocks should not have metadata at the start?
Or is it just completely untrue?
Yes, I know I shouldn't do it. I never would.I am curious about the veracity of this idea; that's it!
By "safe", I mean: "will not cause behaviour other than were the original allocation performed by new, or were the de-allocation performed by delete[]". This means that we might see 1 "element" destruction or n, but no crashing.
Of course it's not true. That person is mixing up several different concerns:
how does the OS handle allocations/deallocations
correct calls to constructors and destructors
UB means UB
On the first point, I'm sure he's correct. It is common to handle both in the same way on that level: it is simply a request for X bytes, or a request to release the allocation starting at address X. It doesn't really matter if it's an array or not.
On the second point, everything falls apart. new[] calls the constructor for each element in the allocated array. delete calls the destructor for the one element at the specified address. And so, if you allocate an array of objects, and free it with delete, only one element will have its destructor invoked. (This is easy to forget because people invariably test this with arrays of ints, in which case this difference is unnoticeable)
And then there's the third point, the catch-all. It's UB, and that means it's UB. The compiler may make optimizations based on the assumption that your code does not exhibit any undefined behavior. If it does, it may break some of these assumptions, and seemingly unrelated code might break.
Even if it happens to be safe on some environment, don't do it. There's no reason to want to do it.
Even if it did return the right memory to the OS, the destructors wouldn't be called properly.
It's definitely not true for all or even most Linuxes, your IRC friend is talking bollocks.
POSIX has nothing to do with C++. In general, this is unsafe. If it works anywhere, it's because of the compiler and library, not the OS.
This question discusses in great details when exactly mixing new[] and delete looks safe (no observable problems) on Visual C++. I suppose that by "on Linux" you actually mean "with gcc" and I've observed very similar results with gcc on ideone.com.
Please note that this requires:
global operator new() and operator new[]() functions to be implemented identically and
the compiler optimizing away the "prepend with number of elements" allocation overhead
and also only works for types with trivial destructors.
Even with these requirements met there's no guarantee it will work on a specific version of a specific compiler. You'll be much better off simply not doing that - relying on undefined behavior is a very bad idea.
It is definitely not safe as you can simply try out with the following code:
#include<iostream>
class test {
public:
test(){ std::cout << "Constructor" << std::endl; }
~test(){ std::cout << "Destructor" << std::endl; }
};
int main() {
test * t = new test[ 10 ];
delete t;
return 1;
}
Have a look at http://ideone.com/b8BiQ . It fails misserably.
It may work when you do not use classes, but only fundamental types, but even that is not guaranteed.
EDIT: Some explanations for those of you who want to know why this crashes:
new and delete mainly serve as wrappers around malloc(), hence calling free() on a newed pointer is most of the time "safe" (remember to call the destructor), but you should not rely on it. For new[] and delete[] however the situation is more complicated.
When an array of classes gets constructed using new[] each default constructor will be called in turn. When you do delete[] each destructor gets called. However each destructor also has to be supplied a this pointer to use inside as a hidden parameter. So before calling the destructor the program has to find the locations of all objects within the reserved memory, to pass these locations as this pointers to the destructor. So all information that is later needed to reconstruct this information needs to be stored somewhere.
Now the easiest way would be to have a global map somewhere around, which stores this information for all new[]ed pointers. In this case if you delete is called instead of delete[] only one of the destructors would be called and the entry would not be removed from a map. However this method is usually not used, because maps are slow and memory management should be as fast as possible.
Hence for the stdlibc++ a different solution is used. Since only a few bytes are needed as additional information, it is the fastest to just over-allocate by these few bytes, store the information at the beginning of the memory and return the pointer to the memory after the bookkeeping. So if you allocate an array of 10 objects of 10 bytes each, the programm will allocate 100+X bytes where X is the size of the data which is needed to reconstruct the this.
So in this case it looks something like this
| Bookkeeping | First Object | Second Object |....
^ ^
| This is what is returned by new[]
|
this is what is returned by malloc()
So in case you pass the pointer you have recieved from new[] to delete[] it will call all destructors, then substract X from the pointer and give that one to free(). However if you call delete instead, it will call a destructor for the first object and then immediately pass that pointer to free(), which means free() has just been passed a pointer which was never malloced, which means the result is UB.
Have a look at http://ideone.com/tIiMw , to see what gets passed to delete and delete[]. As you can see, the pointer returned from new[] is not the pointer which was allocated inside, but 4 is added to it before it is being returned to main(). When calling delete[] correctly the same four is substracted an we get the correct pointer within delete[] however this substraction is missing when calling delete and we get the wrong pointer.
In case of calling new[] on a fundamental type, the compiler immediately knows that it will not have to call any destructors later and it just optimizes the bookkeeping away. However it is definitely allowed to write bookkeeping even for fundamental types. And it is also allowed to add bookkeeping in case you call new.
This bookkeeping in front of the real pointer is actually a very good trick, in case you ever need to write your own memory allocation routines as a replacement of new and delete. There is hardly any limit on what you can store there , so one should never assume that anything returned from new or new[] was actually returned from malloc().
I expect that new[] and delete[] just boil down to malloc() and free() under Linux (gcc, glibc, libstdc++), except that the con(de)structors get called. The same for new and delete except that the con(de)structors get called differently. This means that if his constructors and destructors don't matter, then he can probably get away with it. But why try?
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
( POD )freeing memory : is delete[] equal to delete ?
Does delete deallocate the elements beyond the first in an array?
char *s = new char[n];
delete s;
Does it matter in the above case seeing as all the elements of s are allocated contiguously, and it shouldn't be possible to delete only a portion of the array?
For more complex types, would delete call the destructor of objects beyond the first one?
Object *p = new Object[n];
delete p;
How can delete[] deduce the number of Objects beyond the first, wouldn't this mean it must know the size of the allocated memory region? What if the memory region was allocated with some overhang for performance reasons? For example one could assume that not all allocators would provide a granularity of a single byte. Then any particular allocation could exceed the required size for each element by a whole element or more.
For primitive types, such as char, int, is there any difference between:
int *p = new int[n];
delete p;
delete[] p;
free p;
Except for the routes taken by the respective calls through the delete->free deallocation machinery?
It's undefined behaviour (most likely will corrupt heap or crash the program immediately) and you should never do it. Only free memory with a primitive corresponding to the one used to allocate that memory.
Violating this rule may lead to proper functioning by coincidence, but the program can break once anything is changed - the compiler, the runtime, the compiler settings. You should never rely on such proper functioning and expect it.
delete[] uses compiler-specific service data for determining the number of elements. Usually a bigger block is allocated when new[] is called, the number is stored at the beginning and the caller is given the address behind the stored number. Anyway delete[] relies on the block being allocated by new[], not anything else. If you pair anything except new[] with delete[] or vice versa you run into undefined behaviour.
Read the FAQ: 16.3 Can I free() pointers allocated with new? Can I delete pointers allocated with malloc()?
Does it matter in the above case seeing as all the elements of s are allocated contiguously, and it shouldn't be possible to delete only a portion of the array?
Yes it does.
How can delete[] deduce the number of Objects beyond the first, wouldn't this mean it must know the size of the allocated memory region?
The compiler needs to know. See FAQ 16.11
Because the compiler stores that information.
What I mean is the compiler needs different deletes to generate appropriate book-keeping code. I hope this is clear now.
Yes, this is dangerous!
Dont do it!
It will lead to programm crashes or even worse behavior!
For objects allocated with new you MUST use delete;
For objects allocated with new [] you MUST use delete [];
For objects allocated with malloc() or calloc() you MUST use free();
Be aware also that for all these cases its illegal to delete/free a already deleted/freed pointer a second time. free may also NOT be called with null. calling delete/delete[] with NULL is legal.
Yes, there's a real practical danger. Even implementation details aside, remember that operator new/operator delete and operator new[]/operator delete[] functions can be replaced completely independently. For this reason, it is wise to think of new/delete, new[]/delete[], malloc/free etc. as different, completely independent methods of memory allocaton, which have absolutely nothing in common.
Raymond Chen (Microsoft developer) has an in-depth article covering scaler vs. vector deletes, and gives some background to the differences. See:
http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx
Does delete deallocate the elements
beyond the first in an array?
No. delete will deallocate only the first element regardless on which compiler you do this. It may work in some cases but that's co-incidental.
Does it matter in the above case seeing as all the elements of s are allocated
contiguously, and it shouldn't be possible to delete only a portion of the array?
Depends on how the memory is marke as free. Again implementation dependant.
For more complex types, would delete call the destructor of objects beyond the first one?
No. Try this:
#include <cstdio>
class DelTest {
static int next;
int i;
public:
DelTest() : i(next++) { printf("Allocated %d\n", i); }
~DelTest(){ printf("Deleted %d\n", i); }
};
int DelTest::next = 0;
int main(){
DelTest *p = new DelTest[5];
delete p;
return 0;
}
How can delete[] deduce the number of
Objects beyond the first, wouldn't
this mean it must know the size of the
allocated memory region?
Yes, the size is stored some place. Where it is stored depends on implementation. Example, the allocator could store the size in a header preceding the allocated address.
What if the memory region was
allocated with some overhang for
performance reasons? For example one
could assume that not all allocators
would provide a granularity of a
single byte. Then any particular
allocation could exceed the required
size for each element by a whole
element or more.
It is for this reason that the returned address is made to align to word boundaries. The "overhang" can be seen using the sizeof operator and applies to objects on the stack as well.
For primitive types, such as char, int, is there any difference between ...?
Yes. malloc and new could be using separate blocks of memory. Even if this were not the case, it's a good practice not to assume they are the same.
It's undefined behavior. Hence, the anser is: yes, there could be danger. And it's impossible to predict exactly what will trigger problems. Even if it works one time, will it work again? Does it depend on the type? Element count?
For primitive types, such as char, int, is there any difference between:
I'd say you'll get undefined behaviour. So you shouldn't count on stable behaviour. You should always use new/delete, new[]/delete[] and malloc/free pairs.
Although it might seem in some logic way that you can mix new[] and free or delete instead of delete[], this is under the assumption about the compiler being a fairly simplistic, i.e., that it will always use malloc() to implement the memory allocation for new[].
The problem is that if your compiler has a smart enough optimizer it might see that there is no "delete[]" corresponding to the new[] for the object you created. It might therefore assume that it can fetch the memory for it from anywhere, including the stack in order to save the cost of calling the real malloc() for the new[]. Then when you try to call free() or the wrong kind of delete on it, it is likely to malfunction hard.
Step 1 read this: what-is-the-difference-between-new-delete-and-malloc-free
You are only looking at what you see on the developer side.
What you are not considering is how the std lib does memory management.
The first difference is that new and malloc allocate memroy from two different areas in memory (New from FreeStore and malloc from Heap (Don't focus on the names they are both basically heaps, those are just there official names from the standard)). If you allocate from one and de-allocate to the other you will messs up the data structures used to manage the memory (there is no gurantee they will use the same structure for memory management).
When you allocate a block like this:
int* x= new int; // 0x32
Memory May look like this: It probably wont since I made this up without thinking that hard.
Memory Value Comment
0x08 0x40 // Chunk Size
0x16 0x10000008 // Free list for Chunk size 40
0x24 0x08 // Block Size
0x32 ?? // Address returned by New.
0x40 0x08 // Pointer back to head block.
0x48 0x0x32 // Link to next item in a chain of somthing.
The point is that there is a lot more information in the allocated block than just the int you allocated to handle memory management.
The standard does not specify how this is done becuase (in C/C++ style) they did not want to inpinge on the compiler/library manufacturers ability to implement the most effecient memory management method for there architecture.
Taking this into account you want the manufacturer the ability to distinguish array allocation/deallocation from normal allocation/deallocation so that it is possable to make it as effecient as possable for both types independantly. As a result you can not mix and match as internally they may use different data structures.
If you actually analyse the memory allocation differences between C and C++ applications you find that they are very different. And thus it is not unresonable to use completely different techniques of memory management to optimise for the application type. This is another reason to prefer new over malloc() in C++ as it will probably be more effecient (The more important reason though will always be to reducing complexity (IMO)).