I have a vector that holds a pointer to classes:
vector<Entity*> editorElements;
vector<Entity*> entities;
vector<DirectionalLight*> dirLights;
vector<PointLight*> pointLights;
vector<SpotLight*> spotLights;
This code is within my class Scene. The Scene's ctor and destructors are like so:
Scene()
{
editorElements = vector<Entity*>();
entities = vector<Entity*>();
dirLights = vector<DirectionalLight*>();
pointLights = vector<PointLight*>();
spotLights = vector<SpotLight*>();
}
~Scene()
{
delete[] &entities; // ERROR HERE
delete[] &dirLights;
delete[] &pointLights;
delete[] &spotLights;
delete[] &editorElements;
}
In the destructor I marked a line ERROR HERE. It doesn't matter which vector I put first, I always get the error.
Strange is, it was working fine until lately (wasn't touching anything within the Scene class, or in any other classes that use an instance of Scene) and all of a sudden it raised an exception:
It doesn't matter if the vectors are empty or have elements, it gives the error all the same.
I require assistance to get this sorted out.
The delete expression delete [] x is described thus:
Destroys an array created by a new[]-expression
So delete[] &entities only makes sense if &entities is an array created by a new[]-expression. Right?
But entities is a std::vector<Entity*>, not an Entity[]. You didn't create it with new[], so you must not delete it with delete[].
std::vector isn't syntactic sugar for an array, it's a template class, and std::vector<Entity*> entities isn't an array, it's an object with a constructor and destructor. That also tells us that this statement
entities = vector<Entity*>();
does nothing useful - entities is an object, so it was already default-constructed. You're just default constructing an anonymous temporary of the same type, and assigning it.
Finally, storing raw pointers in a vector is OK here as the vector isn't responsible for the objects' lifetimes. In most situations it's preferable to have the vector own the objects so you don't have to worry about deleting them manually, either directly with
vector<Entity>
or indirectly with
vector<unique_ptr<Entity>>
NB. a good guideline is: you shouldn't be using new, new[], delete or delete[] at all in user code.
Use a class object to manage your storage, because the compiler will take care of calling its constructors and destructors for you.
If you need a custom class, write one that only manages memory, so that stays decoupled from your program logic. Otherwise just use the standard library facilities like std::vector, std::array, std::unique_ptr, std::shared_ptr if you really need that ownership model, etc.
The vectors aren't newed pointers, let alone newed arrays. So you shouldn't be deleting them. If you need to call delete on the pointers stored in the vectors, you should loop over the vectors, deleting each element. But you may be better off storing smart pointers instead (e.g. std::unique_ptr<Entity>. That is if you need to store pointers to dynamically allocated objects at all.
Note that if you do end up deleting elements in the destructor, you will also need to take care of the rule of three/five.
all of a sudden it raised an exception
It is because of trying to delete something you shouldn't be deleting. The delete[] syntax is for deletion of a dynamically allocated array. But you provide it with a pointer to a std::vector instance. So the compiler takes this address for the deletion as if it was an array, which includes finding out its size and then delete the entire segment. But there's no such appropriate figure, as this is not an array, so in run-time you end up trying to delete something in a place you don't have permission to access and thus you get the assertion failure, as this is an access violation, a.k.a. segfault.
Also, vector is a class that manages its own memory. If you wanted to release entities held inside this container -- that is, the individual elements themselves, allocated dynamically -- then you should loop over them and delete each one. Conveniently, for example, using auto and a range-based for loop like this:
for (auto ptr : entities)
delete ptr;
But, in most scenarios you better save yourself this memory management overhead and opt for std::unique_ptr instead of the raw pointers:
#include <memory>
...
std::vector<std::unique_ptr<Entity>> entities;
This way you don't have to worry about freeing any memory as it will be released by the std:: unique_ptr once it's being destructed, as part of the vector's destruction.
Further, this is unnecessary and probably not what you intended to do:
entities = vector<Entity*>();
as the vector object itself is already defined (so it is existing) before this line, and all it does is create an identical new one and assign it to entities.
Related
We have a scenario where we need to create an
std::vector<std::vector<float>> data;
because the vectors aren't at all the same length.
When data gets freed, does every vector inside data also free up its space?
All of the standard library types implement RAII appropriately. That is, any kind of internal dynamic allocation that they perform will be cleaned up automatically by the time the object is destroyed. You never need to worry about it.
In the case of the standard containers, like std::vector, it will automatically ensure that each of its elements is destroyed. Of course, if the elements of the std::vector are themselves std::vectors, they will in turn destroy their elements. Everything is automatic.
You may have seen examples in which you have a std::vector<T*> and the T objects were then allocated manually using new. It's important to realise here that the elements of the vector are not the T objects, but T* objects. The pointers will be cleaned up automatically. Since you manually allocated the T objects, you need to manually deallocate them. (As #Veritas says in the comments, in this case you should prefer using smart pointers)
Yes
Whenever The "Scope" of 'data' ends , The destructor will be automatically called and memory that was allocated for'data' will be freed.
Whenever the destructor is called for a vector then the destructor each of its elements will be called.
Suppose for vector a(5)
Here destructors of a[0],a[1],... will be called.
Similarly in the above case vector< vector > x;
destructors of x[0],x[1] will be called consecutively..
But here each element x[i] is again a vector so again destructors of x[i][0],x[i][1]... will be called..
In this way all elements are destroyed Recursively..
Suppose there's a vector of Items
vector<Item*> items; //{item1, item2, item3}
Then, in other part of the code,
items[1]->suicide();
where the suicide function is:
void Item::suicide()
{
delete this;
}
What is items vector size and how it's arrangement now?
It is okay to do this?
Edit (may I ask an additional question?): If the desired arrangement of the output is {item1, item3}, size is 2, and no dangling pointer, how to do it in a self-destructing way (from the item2 itself)?
Edit 2 : Thanks for all the answers! Awesome. So I finally decided and found the way to do it from outside of the object because it was a bad practice and unnecessarily complicated
What is items vector size and how it's arrangement now? The same. The function call does not change the vector contents nor size at all. It just frees the memory the pointer is pointing to.
Is it okay to do this? More precisely: Is it legal C++? Yes. Is it good style programming? No. Let me elaborate on the latter:
There should be a separation of concerns: Who's responsible for memory management? The container or the user of the class Item or the class Item itself?
Typically the container or user should do that, because he knows what's going on.
What's the way to do that? Memory management in modern and safe C++ code is mostly done using smart pointers like std::shared_ptr and std::unique_ptr and containers like std::vector and std::map.
If the class Item is a value type (that means you can simply copy it and it has no polymorphic behavior in terms of virtual functions), then just use std::vector<Item> instead for your code. Destructors will be called automatically as soon as an element is removed from the container. The container does it for you.
If the class Item has polymorphic behavior and can be used as a base class, then use std::vector<std::unique_ptr<Item>> or std::vector<std::shrared_ptr<Item>> instead and prefer the std::unique_ptr solution, because it adds less overhead. As soon as you stop referring to an object, it will be deleted automatically by the destructor of the smart pointer you are using. You (almost) don't need to worry about memory leaks anymore.
The only way you can produce memory leaks is that you have objects that contain std::shared_ptrs that refer to each other in cyclic way. Using std::unique_ptrs can prevent this kind of trouble. Another way out are std::weak_ptrs.
Bottom line: Don't provide a function suicide(). Instead put the responsibility solely into the hands of the calling code. Use standard library containers and smart pointers to manage your memory.
Edit: Concerning the question in your edit. Just write
items.erase( items.begin() + 1 );
This will work for all types: std::vector of values or pointers. You can find a good documentation of std::vector and the C++ Standard library here.
The suicide member doesn't change the vector. So the vector contains an element which is an invalid pointer and formally you can't do much with an invalid pointer, even copying or comparing it is undefined behavior. So anything which access it, included vector resizing, is an UB.
While any access if formally UB, there is a good chance that your implementation doesn't behave strangely as long as you don't dereference the pointer -- the rationale for making any access UB is machines where loading an invalid pointer in a register can trap and while x86 is part of them, I don't know of widespread OS working in this mode.
Your suicide function does not to anything with the Items vector, let alone it knows anything about it. So from the vector's point of view: nothing changes when you call the function and it's ok to do that.
The pointer will become invalid, that's all. You should be careful to not to delete it again. vector<Item*> will NOT delete elements on its own.
The vector has no idea what you're doing elsewhere in the code, so it'll keep a dangling pointer to the original Item.
"Is it OK do do that?"
After suiciding the item, you should adjust the vector manually to no longer keep that dangling pointer.
That's ok in case of vector of pointers as vector will not call Item's destructor. But you have to somehow know which pointers are still valid.
If you are storing Items in vector by value, calling Item's destructor is not ok. When vector will be destroyed or cleared, it will call item's destructor again, causing application crash.
Wow, It seems that you make a typing error. It should be vector<Item *> Items;
As to your question:
the size of vector Items does not change, means that, it still has three pointers to Item objects.
the content of the vector does not change:
before Items[1]->suicide() , Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
after Items[1]->suicide(), Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
It's definitely OKAY to do so.
Besides, the vector will manage its memory automatically, when you push some elems into it while the capacity is not enough, it will reallocate a larger space, BUT, when you pop some elems or erase some elems, it will never give the redundant memory to the system.
The code of Items[1]->sucide() just return the memory held or pointed by the pointer Items[1] to the system, it will do nothing on the pointer itself, Items[1] still holds the same value, but point an unsafe area.
Unexpectedly, you have made a Design Pattern, suppose you want to design a class and you ONLY allow allocate any object of it on the Heap, you may write the following code:
class MustOnHeap
{
private:
~MustOnHeap() { // ...}
public:
void suicide() { delete this;}
};
Then ,the class can not have any instance that is alloacated on the stack, because the destructor is private, and the compiler must arrange the calling of destructor when the object walk out its scope.
Therefor, you must allocate them on the heap, MustOnHeap* p = new MustOnHeap; and then destroy it explicitly : p->suicide();
From the vector docs it would appear that the proper way to completely deallocate a vector of values to which you have a class member pointer such as:
std::vector<MyObject>* mvMyObjectVector_ptr;
...
//In the class constructor:
mvMyObjectVector_ptr = new std::vector<MyObject>();
would be to invoke the following, in order, in the class's destructor implementation
mvMyObjectVector_ptr->clear();
delete mvMyObjectVector_ptr;
However, this appears to be leading to SIGABRT 'pointer being freed was not allocated' errors. Is the above idiom the correct way to completely deallocate the memory held at the address pointed to by a pointer to a vector (if it is, I assume my errors are coming from something else)? If not, what is the correct way?
Yes, it is correct, provided mvMyObjectVector_ptr has been allocated using new.
Additionally, MyObject needs to satisfy certain requirements before it can be used with std::vector.
The call to clear() is redundant and can be omitted.
Some likely reasons for the SIGABRT include:
mvMyObjectVector_ptr hasn't been allocated using new;
MyObject violates the Rule of Three;
the class the contains the vector violates the Rule of Three.
I don' think your problem lies in the code you have shown us.
This line:
//In the class constructor:
suggests you are using this inside a class and not implementing the rule of three correctly.
A better idea is not to use a pointer to a vector.
Just declare it as a normal automatic member.
class MyClassContainingVector
{
public:
std::vector<MyObject> mvMyObjectVector;
// ^^^^^ notice no pointer.
};
Now it will be created and destroyed correctly and automatically.
Neither your constructor or destructor will need any code to manage this object.
Yes, dynamically allocating a std::vector object by calling new and invoking its destruction by calling delete will result in memory that has been internally used for holding its elements being freed.
However it would be much simpler and more reliable to follow RAII idiom and use an object with automatic storage duration:
{
std::vector<MyObject> myVector;
...
} // <-- memory is freed here
when execution leaves this scope (note that it could be also caused by exception being thrown etc.), it is guaranteed that myVector object will be destructed and memory will be freed.
Vectors usually shouldn't be held as dynamically allocated pointers. They should be just member variables of your class, in most situations (though there are always exceptions). If they are pointers allocated by 'new', and simple 'delete' should work.
Vectors handle memory allocation for you, so you don't have to. However, if you want to truly free all the storage memory held in a vector, even if it's on the stack, there's a new function for that.
Because vector.reserve() only expands memory, but never shrinks it, in C++11, a new function was added for the purpose of freeing the reserved memory: vector.shrink_to_fit(). Implementations and free to do what they want with it, but you're basically asking the implementation to free the memory, so they should answer the request in a reasonable way.
You can truly clear a vector by going like this:
vector.clear(); //Erases the elements.
vector.shrink_to_fit(); //Erases the memory no longer needed by the elements.
The reasons why vectors hold onto their memory is for performance reasons, so you should only do this if you actually understand why they have memory in reserve, and are willing to deal with (or know you won't have to deal with) any performance hits that result from micro-managing the memory.
In my simple game engine I have a vector containing pointers to entities. Each entity is allocated with the new keyword. To call functions on my entities I use an iterator and so when deleting my entities I figured I'd use an iterator as well, like so:
vector<Entity*>::iterator iter;
for (iter = gameEntitys.begin(); iter != gameEntitys.end();) {
delete (*iter);
++iter;
}
But I now have a horrific memory leak and all profiling tools point towards the line delete (*iter);
Clearly there is something wrong but what is the correct way for me to delete the entities contained in the vector (and clear the vector for another scene). Using gameEntitys.clear(); is useless to my knowledge as it only removes the elements of the vector not actually calling delete on them as they are pointers rather than actual data.
Edit: I have bee watching the comments. The Entity class is not polymorphic and does not have any subclasses. Would it make more sense if I stopped using dynamic memory and had a normal array of non-pointer entities?
The reason I know there is a memory leak is because when the application starts the memory use shoots up to more than 2gb before crashing.
Most likely, the memory leak is coming from the destructor of your Entity or one of its subclasses: you are performing your delete operations correctly, so the destructor itself must be at fault. One common problem is not making destructors virtual in a polymorphic class hierarchy.
You are also absolutely right about uselessness of calling gameEntitys.clear(): it will leak your objects "wholesale" by "forgetting" the references to them.
If you are on C++11, consider changing the definition to use std::unique_ptr
std::vector<std::unique_ptr<Entity> > gameEntitys;
This will free you from the need to manage the memory of your entries manually, while letting you keep pointers to objects of derived classes in your vector. If you use unique_ptr, calls to gameEntitys.clear() will destroy the items pointed to by vector's elements.
Dealing with the vector of unique_ptr is somewhat different (for example, inserting new items requires extra care, see this answer for details) but I think the positives of simplified memory management compensate for the slight inconveniences.
EDIT : Since your Entity class is not polymorphic, consider switching to std::vector<Entity>, unless you plan to switch to a polymorphic hierarchy later on.
I am writing an application using openFrameworks, but my question is not specific to just oF; rather, it is a general question about C++ vectors in general.
I wanted to create a class that contains multiple instances of another class, but also provides an intuitive interface for interacting with those objects. Internally, my class used a vector of the class, but when I tried to manipulate an object using vector.at(), the program would compile but not work properly (in my case, it would not display a video).
// instantiate object dynamically, do something, then append to vector
vector<ofVideoPlayer> videos;
ofVideoPlayer *video = new ofVideoPlayer;
video->loadMovie(filename);
videos.push_back(*video);
// access object in vector and do something; compiles but does not work properly
// without going into specific openFrameworks details, the problem was that the video would
// not draw to screen
videos.at(0)->draw();
Somewhere, it was suggested that I make a vector of pointers to objects of that class instead of a vector of those objects themselves. I implemented this and indeed it worked like a charm.
vector<ofVideoPlayer*> videos;
ofVideoPlayer * video = new ofVideoPlayer;
video->loadMovie(filename);
videos.push_back(video);
// now dereference pointer to object and call draw
videos.at(0)->draw();
I was allocating memory for the objects dynamically, i.e. ofVideoPlayer = new ofVideoPlayer;
My question is simple: why did using a vector of pointers work, and when would you create a vector of objects versus a vector of pointers to those objects?
What you have to know about vectors in c++ is that they have to use the copy operator of the class of your objects to be able to enter them into the vector. If you had memory allocation in these objects that was automatically deallocated when the destructor was called, that could explain your problems: your object was copied into the vector then destroyed.
If you have, in your object class, a pointer that points towards a buffer allocated, a copy of this object will point towards the same buffer (if you use the default copy operator). If the destructor deallocates the buffer, when the copy destructor will be called, the original buffer will be deallocated, therefore your data won't be available anymore.
This problem doesn't happen if you use pointers, because you control the life of your elements via new/destroy, and the vector functions only copy pointer towards your elements.
My question is simple: why did using a
vector of pointers work, and when
would you create a vector of objects
versus a vector of pointers to those
objects?
std::vector is like a raw array allocated with new and reallocated when you try to push in more elements than its current size.
So, if it contains A pointers, it's like if you were manipulating an array of A*.
When it needs to resize (you push_back() an element while it's already filled to its current capacity), it will create another A* array and copy in the array of A* from the previous vector.
If it contains A objects, then it's like you were manipulating an array of A, so A should be default-constructible if there are automatic reallocations occuring. In this case, the whole A objects get copied too in another array.
See the difference? The A objects in std::vector<A> can change address if you do some manipulations that requires the resizing of the internal array. That's where most problems with containing objects in std::vector comes from.
A way to use std::vector without having such problems is to allocate a large enough array from the start. The keyword here is "capacity". The std::vector capacity is the real size of the memory buffer in which it will put the objects. So, to setup the capacity, you have two choices:
1) size your std::vector on construction to build all the object from the start , with maximum number of objects - that will call constructors of each objects.
2) once the std::vector is constructed (but has nothing in it), use its reserve() function : the vector will then allocate a large enough buffer (you provide the maximum size of the vector). The vector will set the capacity. If you push_back() objects in this vector or resize() under the limit of the size you've provided in the reserve() call, it will never reallocate the internal buffer and your objects will not change location in memory, making pointers to those objects always valid (some assertions to check that change of capacity never occurs is an excellent practice).
If you are allocating memory for the objects using new, you are allocating it on the heap. In this case, you should use pointers. However, in C++, the convention is generally to create all objects on the stack and pass copies of those objects around instead of passing pointers to objects on the heap.
Why is this better? It is because C++ does not have garbage collection, so memory for objects on the heap will not be reclaimed unless you specifically delete the object. However, objects on the stack are always destroyed when they leave scope. If you create objects on the stack instead of the heap, you minimize your risk of memory leaks.
If you do use the stack instead of the heap, you will need to write good copy constructors and destructors. Badly written copy constructors or destructors can lead to either memory leaks or double frees.
If your objects are too large to be efficiently copied, then it is acceptable to use pointers. However, you should use reference-counting smart pointers (either the C++0x auto_ptr or one the Boost library pointers) to avoid memory leaks.
vector addition and internal housekeeping use copies of the original object - if taking a copy is very expensive or impossible, then using a pointer is preferable.
If you make the vector member a pointer, use a smart pointer to simplify your code and minimize the risk of leaks.
Maybe your class does not do proper (ie. deep) copy construction/assignment? If so, pointers would work but not object instances as the vector member.
Usually I don't store classes directly in std::vector. The reason is simple: you would not know if the class is derived or not.
E.g.:
In headers:
class base
{
public:
virtual base * clone() { new base(*this); };
virtual ~base(){};
};
class derived : public base
{
public:
virtual base * clone() { new derived(*this); };
};
void some_code(void);
void work_on_some_class( base &_arg );
In source:
void some_code(void)
{
...
derived instance;
work_on_some_class(derived instance);
...
}
void work_on_some_class( base &_arg )
{
vector<base> store;
...
store.push_back(*_arg.clone());
// Issue!
// get derived * from clone -> the size of the object would greater than size of base
}
So I prefer to use shared_ptr:
void work_on_some_class( base &_arg )
{
vector<shared_ptr<base> > store;
...
store.push_back(_arg.clone());
// no issue :)
}
The main idea of using vector is to store objects in a continue space, when using pointer or smart pointer that won't happen
Here also need to keep in mind the performance of memory usage by CPU.
std::vector vector guarantees(not sure) that the mem block is
continuous.
std::vectorstd::unique_ptr<Object> will keep smart-pointers in continuous memory, but real memory blocks for objects can be placed in different positions in RAM.
So I can guess that std::vector will be faster for cases when the size of the vector is reserved and known. However, std::vectorstd::unique_ptr<Object> will be faster if we don't know the planned size or we have plans to change the order of objects.