Is it safe to delete an array pointer in C++ after reassignment? - c++

Suppose I'd like to swap two array pointers in C++ which I have allocated with new [] and different length. Is it safe to delete [] them after swapping? What if they have the same length?
int *a;
int *b;
int *tmp;
a = new int[5];
b = new int[10];
tmp = a;
a = b;
b = tmp;
delete [] a;
delete [] b;

Yeah, you can. The reason being is that the information needed to accurately free up that memory is managed by the free store (the heap in most cases). So it knows how to delete based on address rather than variable. Often times this information is held in *(ptr - x) where x is the size of the tracking data.

Is it safe to delete [] them after swapping?
Yes.
What if they have the same length?
The length is irrelevant.

Yes, you can surely delete the pointer once your swapping is done. As you no longer need to point your array so in that case, it is safe to delete after swapping.
int *a;
int *b;
int *tmp;
a = new int[5];
b = new int[10];
tmp = a;
a = b;
b = tmp;
delete [] a;
delete [] b;
And this is the correct way of doing it. Great Job

Related

Deleting elements of a dynamic array one-by-one

I want to delete a dynamically-allocated array by looping through all the elements and calling delete on each of them.
(I am doing this because I have to "move" an array to another location, that is, to copy the original array and then delete it, but that would take 2x the time than simultaneously copying each element and calling delete on them individually)
I have the following code:
int main()
{
int *n=new int[2];
delete n;
delete (n+1);
}
But i am getting a Segmentation error each time i run this....
Although, this works fine -:
int main()
{
int *n=new int[1];
delete n;
}
So, my guess is that delete is somehow deleting the whole array instead of a single element!
Could anyone please explain if my guess is right, and if it is, suggest a possible workaround?
I am using GCC 4.7.3 on Ubuntu 13.04
You cannot delete the elements individually. When you allocate with new [] you must deallocate with delete []. What you are doing here:
int *n=new int[1];
delete n; // ERROR: should be delete []
it not correct. You are invoking undefined behaviour. It seems to work by pure chance and cannot be relied on.
As for a workaround, it isn't clear what the problem is, but if you want to "move" the array, you could just assign it to a different pointer:
int* n=new int[2];
...
int* m = n;
n = nullptr;
....
delete [] m;
To delete
int *n=new int[2];
use
delete [] n;
the code
delete n;
is wrong when you allocate using new [].

How memory will be deleted?

Let's say I have structure
struct Foo {
int whatever;
int whatever2;
...
};
And I have this type of array
Foo **array = new Foo*[128];
Then, to every pointer I assign new structure
for (int i = 0; i < 128; i++)
array[i] = new Foo;
Then, after a while I deallocate:
delete[] array;
How memory will be deallocated?
Only the space for pointers will be freed
Space for pointer + the objects pointed by those pointers themselves?
Your code leaks memory. You need to call delete once for every new call (assuming the new doesn't fail and either return NULL or throw bad_alloc). So, in this case, you'll need to have a similar loop to the one that calls array[i] = new Foo; that does delete array[i];
I think this is one of points in Scott Meyers book, Effective C++ have read long back. But basic idea is, to avoid memory leak when you use new. make sure to call delete as many times as new is called and map new with delete and new[] with delete[] accordingly. so in your case new is called 128 times in for loop and new[] is called once, so similarly delete should be called same way to array[i] 128 times and delete[] should be called once for array. Hope this helps.

create a dynamic array while delaying object construction

I'd like to be able to "somehow" create a dynamic array that would still let me build its elements using the new operator.
Here's what I'd like to achieve:
A* a = new A[3]; //or any equivalent syntax
new (&a[0]) A(myparams1); //placement new on first slot
new (&a[1]) A(myparams2, ...); //placement new on 2nd slot
new (&a[2]) A(myparams3, ...); //placement new on 3rd slot
delete[] a; //correct deletion of all elements
I'm aware that this code would work (minus the 3 elements overwritten), but I'd like to avoid creating 3 default a elements in the first call to new[]. I am assuming here that I will always place 3 elements before calling delete[].
I'm thinking such a thing can be achieved by using intelligent calls to A::operator new[] but I'm not sure how.
Does anyone have any idea? it's mostly for curiosity
You just get raw memory instead:
void* mem = ::operator new(capacity * sizeof(A));
This is required to be aligned for any type, including an array of A's. Now you can construct in it:
for (std::size_t i = 0; i < capacity; ++i)
{
void* addr = static_cast<char*>(mem) + i * sizeof(A);
new (addr) A(x, y, z, ...);
}
Destruction requires you explicitly invoke it:
for (std::size_t i = 0; i < capacity; ++i)
{
void* addr = static_cast<char*>(mem) + i * sizeof(A);
static_cast<A*>(addr)->~A();
}
And now you can free the raw memory:
::operator delete(mem);
Note that none of this is exception-safe. It's also what std::vector<A> does, check out the code.
Use operator new.
A a* = (A*) ::operator new(sizeof(A) * 3);
new (&a[0]) A(/* whatever */);
//do stuff
a[0].~A();
::operator delete(a);
Pay careful attention to manually calling the destructors. When using placement new the destructor is not called automagically so it's up to you.
You can create array of pointers.
A ** a = new A*[3]
a[0] = new A;
a[1] = new A;
a[2] = new A;
You need to call delete on each allocated element
delete a[2];
delete a[1];
delete a[0];
And to delete array itself delete[] a;

Requesting a specific address for the new operator

Say that I want to allocate an array of ints.
int* array = new int[5];
and then later on assume I have 5 int pointers, all pointing to the 5 different integers of the array.
int* v1 = &array[0];
int* v2 = &array[1]; //etc..etc
Now that I have "remembered" the location of all the ints in the array, I would like to manage the elements as individual integers. So in theory if I then set my array pointer to NULL...
array = NULL;
I would in theory not have to worry, because all my v1 and v2 pointers are pointing to all the elements in the array. The problem then is say like I am done with v2. So I would like to delete v2 to free up those 4 bytes.
delete v2;
Unfortunately, when I try to do that, bad things happen. I assume because the memory allocation table says "Hey, you can't delete in that space because it currently belongs to part of an int array!"
So thats fine, I would then like to say
delete [] array;
but if I do that, I want to make sure that when I do...
int* v1 = new int;
I want to guarantee that the newly allocated integer was created at the address of array[0]. So is there a way to specify where a new value is created? Or can I somehow control the memory list?
I've attempted to use the placement operator by calling something like...
int* v1 = new((void*)&array[0]) int;
but then when I delete the array with the delete operator and then attempt to access v1 by dereferenceing it... say
cout<<*v1;
I get a bunch of text to the screen that says "double free or corruption (fasttop): ...
I am using Ubuntu 11.04 and g++ compiler in codeblocks.
Also, just FYI, I have looked at Create new C++ object at specific memory address? and that is where I got the information about the placement operator, but it appears to not be working the way I need it to work.
#include <iostream>
using namespace std;
int main()
{
int *array = new int[20];
for(int i=0;i<4;i++)
{
array[i] = i;
}
int* a = new ((void*)&array[0]) int;
int* b = new ((void*)&array[1]) int;
int* c = new ((void*)&array[2]) int;
int* d = new ((void*)&array[3]) int;
int* e = new ((void*)&array[4]) int;
cout<<*a<<endl;
cout.flush();
delete[] array;
cout<<*a;
delete a;
delete b;
delete c;
delete d;
delete e;
return 0;
}
A correction:
int *v1 = array[0];
int *v2 = array[1];
should be
int *v1 = array;
int *v2 = array + 1;
Also, if you allocate new int[5], you can only free the memory for the entire array and not for individual elements.
"I want to guarantee that the newly allocated integer was created at the address of array[0]"
If that is the case, why should you go for a newly allocated integer? Just assign array to v1 as shown above.
Allocation of memory does not work the way you have used and neither can you release memory in the manner you are trying to.
A placement new "creates" an object at the given location by calling the constructor of the object but does not allocate memory and hence the memory used by placement new cannot be released by a delete. Memory should be pre-allocated before a call to placement new and the memory can be released based on how the pre-allocation was made.
Usage : Placement new.
Also, I found an example from a blog (not mine): Placement new
delete v2;
You should not delete elements individually allocated with placement new, release all the memory at one time when you are finished with it, like this delete [] array; (for a more detailed explanation).
And updating your code:
#include <iostream>
using namespace std;
int main()
{
int *array = new int[20];
for(int i=0;i<5;i++) // Still leaves garbage in rest of array
{
array[i] = i;
}
int* a = new (array) int;
// int* a = new(&array[0]) int;
int* b = new (array + 1) int;
int* c = new (array + 2) int;
int* d = new (array + 3) int;
int* e = new (array + 4) int;
cout << *a << " " << *b << " " << *c << " " << *d << " " << *e << endl;
delete[] array;
}
Couple of pointers:
1) cout.flush(); is unnecessary because std::endl calls flush() already.
2) I see no reason why placement new should be used here, take a look at this SO question to see reasons why you should use it. In your above example, int array[5]; and int* a = array; would be fine. Also, in a linked list the idea is that elements can be easily inserted and removed, if you allocate an array, you cannot delete the array and expect to be able to use the memory afterward (that would result in UB). So you have to choose between using an array or linked list, you can't have both (well, you could simulate a linked list to a certain extent).
3) Like I mentioned above, call delete [] array; after you are finished using the memory and do not dereference pointers into that memory or call delete on pointers into that memory once you have freed the memory.

Arrays & Pointers

Looking for some help with arrays and pointers and explanation of what I am trying to do.
I want to create a new array on the heap of type Foo* so that I may later assign objects that have been created else where to this array. I am having troubles understanding what I am creating exactly when I do something like the following.
Foo *(*f) = new Foo*[10];
Also once I have created my array how do I access each element for example.
(f + 9)->fooMember(); ??????
Thanks in advance.
Foo *(*f) = new Foo*[10];
The parentheses in the declaration are unnecessary, so this is the same as:
Foo **f = new Foo*[10];
In any case, the new Foo*[10] allocates space for ten Foo*s and leaves them uninitialized. It returns a pointer to the initial Foo* in the array (the zeroth element), which you assign to f.
To access elements of the array, you simply use subscripting:
f[0] = new Foo;
f[0]->fooMember();
Remember that anything you create using new[] must be freed once when you are done with it by calling delete[] on the pointer. For example:
delete[] f;
This does not delete the elements pointed to by the Foo*s in the array. If you create Foo objects using new, you must delete them before you delete the array. For example, to free the element we created above:
delete f[0];
You can create an array of pointers using the following code:
Foo** f = new Foo*[10];
Then access the elements with:
f[9]->fooMember();
Be sure to clean up afterwards:
delete[] f;
Thanks.
When you have this situation, you might find the following code snippet useful:
First the initialization:
Foo** f = new Foo*[10];
for (int i = 0; i < 10; i++) {
f[i] = new Foo;
}
Then to access each element in the f array which is what you asked, but you won't be able to do so unless you allocate memory properly for each member by calling the constructor as done above:
f[9]->fooMember();
Finally, to keep things tidy and to prevent memory leaks:
for (int i = 0; i < 10; i++) {
delete f[i];
}
delete[] f;
Arrays and pointers aren't very C++ish. How about
std::vector<std::shared_ptr<Foo> > f;
f.push_back(std::make_shared<Foo>(whatever, arguments, you, need));
// ...
f[9]->fooMember();
// ...
No manual cleanup needed :-)