compiling is okay but assignment error of shared_ptr occurs - c++

I think it may probably an assignment error of shared_ptr. I wrote some code regarding my error about shared_ptr of vector containing int pointer. The error occurs the 2-th loop of j-loop. Please let me know what's the mistake in the code. And I wonder whether 'delete vec.get()' is correct for free the memory of the vector.
int i,j;
shared_ptr<vector<int*>> vec = NULL;
for (j = 0; j < 2; j++)
{
vec = shared_ptr<vector<int*>>(new vector<int*>());
for (i = 0; i < 5; i++)
{
int* ia = new int[10];
vec->push_back(ia);
}
delete vec.get();
}

From what you are showing, there is no need for the smart pointer or the raw pointers. The following code has the same effect as what you seem to intend, except that it also properly initializes all the int elements to zero, which your current code does not do:
vector<vector<int>> vec;
for (int j = 0; j < 2; j++)
{
vec = {5, vector<int>(10)};
// Do something with vec
}
The concrete problem with your current code is that you are trying to delete the raw pointer owned by the shared_ptr. The shared_ptr will delete the owned pointer when its own lifetime ends and no other shared_ptr instance referring to the raw pointer exists anymore. That is its purpose.
If you want to delete the int array you allocated for the int* pointers in the vector, then you need to decide which of the pointers at which index you want to delete:
delete[] (*vec)[index];
vec is the shared_ptr, *vec is a reference to the owned vector<int*>, (*vec)[index] is a reference to the int* stored in the vector<int*> at index index. You need to use delete[] instead of delete, because you allocated with the array form of new.
Given the way your code is structured, you would need to call delete[] for each index of the vector once to avoid any memory leak. Since doing that manually before the vector is destroyed violates the RAII principle, one would use std::unique_ptr for the inner int* instead of raw new. That being said, I already mentioned above that I don't see any reason for pointers of any kind at all.

Below code should work for you:
for (int j = 0; j < 2; j++)
{
auto vec = std::make_shared<vector<int*>>();
for (int i = 0; i < 5; i++)
{
int* ia = new int[10];
vec->push_back(ia);
}
for (int i = 0; i < 5; i++)
{
delete[] vec.get()->at(i);
}
}
I do not understand requirement of this type of strange code. If you are using smart pointer, Why Share_ptr instead unique_ptr? why to call delete? Why you allocate the memory to int* when can be handled by vector of integer. Think on it.
No need to declare and then allocate the memory.
Hope this will help you.

Related

Free dynamic array of static arrays?

I have code similar to this
EDIT this code is supposed to be on interface so only POD is allowed. No vectors, no containers.
int (*neco)[2];
int ahoj = 2;
neco = new int[ahoj+2][2];
int iter = 1;
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 2; j++)
{
neco[i][j] =iter;
iter++;
}
}
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
This does not work. The delete deletes memory not allocated.
Not even
delete[] neco;
Or any other delete. Everyone of them deletes memory BEFORE the allocated block.
Googling and consulting with peers in the office had no results. :)
How do I allocate dynamic array of "points" (two coordinates) and then free them?
I am able to solve the problem via using different structure.
But apperently I am able to allocate the memory. Write in the allocated memory…
How do I correctly free this memory? (Just accademic question.)
Plain pointers to dynamically allocated memory get you into troubles.
Use a std::unique_ptr:
#include <memory>
// ...
std::unique_ptr<int[][2]> neco(new int[ahoj+2][2]);
And remove that loop with delete[].
Alternatively, use std::vector<int[2]> neco(ahoj+2) - it does memory management for you and can be resized.
The general rule is that every new expression must be matched by a single corresponding delete expression.
Your new expression is the right hand side of the statement
neco = new int[ahoj+2][2];
so the corresponding delete expression is given in the statement
delete [] neco;
If that doesn't work (which is what you claim) it means the problem is in some other code exhibiting undefined behaviour.
Your loop
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
is incorrect because none of the neco[i] are the result of a new expression. So delete [] neco[i] has undefined behaviourin every loop iteration.
Given that your code sample(s) and description are incomplete, I doubt anyone else can give more useful advice.
Also, you are mistaken in your belief that you can't use a standard container. You can.
#include <vector>
int main()
{
std::vector<int[2]> avec(ahoj + 2);
int (*neco)[2] = &avec[0];
for (size_t i = 0; i < ahoj + 2; ++i)
{
for (size_t j = 0; j < 2; ++j)
{
neco[i][j] = iter;
++iter;
}
}
}
The only difference is that avec does the dynamic memory allocation and deallocation for you. neco is still a pointer to an array as required (according to your description) by your API. The two constraints on this approach are;
don't resize theavec after initialising neco (or reinitialise neco whenever avec is resized)
don't use neco after avec ceases to exist (since the behaviour will then be undefined).
Also, none of the arrays are actually static. So your question is mistitled.
If I can recall properly, an array of arrays (being dynamic or static), is basicly a matrix.
So, the academic answer:
The same way you allocate memory (first allocate the memory of the array of arrays, then with a foryou allocate the memory of the arrays inside the array), to free it, you need to delete in a forthe memory of the arrays, and then, in a simple delete, free the memory of the dynamic array.
So:
arrayOfArrays[[array1][array2][array3][array4]]
means: allocate memory of arrayOfArrays, then in a loop, allocate memory of array(number)
Same goes the other way around.
Free memory of arrayOfArraysin a single sentence.

How to delete dynamic elements stored in a std::forward_list

I'm using a std::forward_list in C++ to store dynamically allocated elements. I'm wondering what the correct way to 'delete' the elements in list, or free the memory.
std::forward_list<int> integerList;
for (int i = 0; i < 5; i++) {
int* intPtr = new int(i);
integerList.push_front(*intPtr);
}
After this code executes, I think what should happen is the forward_list holds a dynamically allocated int. Now, how would I go about properly calling delete on it? I noticed the forward_list container has a clear() function, but does that call delete on all of the elements in each node?
I think what should happen is the forward_list holds a dynamically allocated int
No, it doesn't hold dynamically allocated int. The type of element is int, when integerList.push_front(*intPtr);, the value will be copied.
On the other hand, you get a memory leak in the for loop, you need to delete what you newed.
for (int i = 0; i < 5; i++) {
int* intPtr = new int(i);
integerList.push_front(*intPtr);
delete intPtr;
}
If you want to save dynamically allocated elements, you should declare the type of element as pointer, and delete the elements by yourself at last.
std::forward_list<int*> integerList;
for (int i = 0; i < 5; i++) {
int* intPtr = new int(i);
integerList.push_front(intPtr);
}
...
for (auto e : integerList) {
delete e;
}
And you could use smart pointers to avoid this kind of memory management, such as std::unique_ptr or std::shared_ptr.
Yes, you will have to iterate through the list and call delete each pointer element.

Destroy pointers to objects in array

Say I want to declare an array of pointers to a specific object like
Object *objects = new Object[size];
and then add some new objects to my dynamically allocated array
for (int i = 0; i < size; i++){
Object* obj = new obj;
objects[i] = *obj;
}
is it enough to deallocate all memory by just calling delete[] on the array, or do I have to loop through the array first and call delete on each object? Or is this stupid to do in practice?
You always have to delete everything you new in some way. That means, you would need to delete obj in every iteration to avoid leaks. Note that you never really store the Object obj points to, but a copy of it.
The way you do it right know is quite unusual and not very handy anyway: The loop you showed does nothing useful since the new Objects[size] already default constructed your Objects. In particular, it does not add any elements, they are already there. You could just leave that out. If you want to change the content of your array, e.g. do more initialization, your loop would usually look more like this
for (int i = 0; i < size; i++){
objects[i] = newValue;
}
Remember, the Objects are already there after new Objects[size]!
In practice, you would be much better of with a
std::vector<Object> objects(size);
(or maybe, if the above does not fit your usecase, a
std::vector<std::unique_ptr<Object>> objects(size);
, but I feel like that is unlikely to be the case). For a good overview of what a std::vector can do and how to use it, read the documentation. Probably most importantly for you: You can index it just like an array.
First, you have to follow the deallocation is reverse order of allocation.
So number of times new that many times delete , similarly number of times new [] that many times delete []
// Assuming objects as array of pointers [ Object **objects ]
for (int i = 0; i < size; i++)
{
delete objects[i] ;
}
delete [] objects;
And your correct allocation should go as:
Object **objects= new Object*[size];
for (int i = 0; i < size; i++) {
objects[i] = new Object;
}
Also , you should use smart pointers std::unique_ptr for hassle free memory management
std::vector< std::unique_ptr<Object> > objects ;
You are storing an array of Objects and not pointers to Object. This means that they won't be deleted when you delete the array and the memory will leak.
If you want to store pointers to Objects in your array then you need to declare it as Object **objects = new Object *[size]; and then you will have to delete all the pointers in the array.
So the better code will look like:
//Allocation:
Object **objects = new Object *[size];
for (int i = 0; i < size; i++){
objects[i] = new Object;
}
//Deletion
for (int i = 0; i < size; i++){
delete objects[i];
}
delete [] objects;
An even better solution would be to use vectors and smart pointers and then you don't need the deletion code at all.
//Allocation:
vector<unique_ptr<Object>> objects;
for (int i = 0; i < size; i++){
objects.push_back(make_unique(new Object));
}
//Deletion
//Hey where did all the code go.

Proper way to delete an array of pointers

I have an array of pointers (that I created by calling new ptr*[size]). All of these pointers point to an object that was also put on the heap.
What is the proper way to delete the array and all new'd ptr's?
This is what I do now:
for (int i = 0; i < size; i++) delete array[i];
delete[] array; // Not sure since this double deletes array[0]
Does this do what I think it should?
Thanks
Every pointer allocated with new gets a corresponding delete. Every pointer allocated with new [] gets a corresponding delete []. That's really all you need to know. Of course, when you have a dynamically allocated array which contains dynamically allocated pointers the deallocation must occur in reverse order.
So it follows that the correct idiom would be...
int main()
{
int **container = new int*[n];
for(int i = 0; i < n; ++i)
container[i] = new int[size];
// ... and to deallocate...
for(int i = 0; i < n; ++i)
delete [] container[i];
delete [] container;
}
And then of course I say "stop doing that" and recommend you use a std::array or std::vector (and the template type would be unique_ptr<int>).
Yes, that does what you think it should. Since you did new for each element, you have to delete each element. And since you did new[] for the entire array, you need to delete[] the entire array.
As #djechlin rightly says in the comments, there's not really enough information to go on, but I'm presuming your prior code is something like this:
int** array = new int*[5];
for (int i = 0; i < 5; i++) {
array[i] = new int;
}
Note that array is not actually an array type. It is a "pointer to pointer to int" and the array of pointers it points to was allocated with new[]. That's why you need to delete[] it.
Yes. First you have to free the object each pointer in the array points to, then you have to free the array itself. In that order. If you reverse the order you'll have no reference to the objects and will leak a lot of memory.
Yes, first you delete each object to which elements of array point, and then you delete array of pointers itself. If you want to check your memory management, you can use tools like valgrind, they will be able to spot most errors.

Filling an array of pointers, deleting when exiting

In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.