removing things from a pointer vector - c++

I have a vector of pointers like so:
vector<Item*> items;
I want to clear it. I've tried:
for (unsigned int i = 0; i < items.size(); i++)
delete items.at(i);
items.clear();
,
while (!items.empty())
{
delete items.back();
items.pop_back();
}
,
while (!items.empty())
{
delete items.at(0);
items.erase(items.begin());
}
, and
while (!items.empty())
delete items.at(0);
Every single one of these blows up for some reason or another, including deletion of already deleted objects and out of range vector iterators.
What do I do? I want to be able to reuse that same vector and add more Item pointers into it later. Just using delete without clearing still leaves junk pointers in there, right?
EDIT: Okay, I've switched to shared_ptrs. Now I have
vector<shared_ptr<Item> > items;
Yet, when I do items.clear(); , I get the error "vector iterators incompatible". What am I still doing wrong?

I ran a test with all your ways of deleting stuff, and one of them simply doesn't work. See the code below for the comments on them.
To answer your question "what do I do," here is what I do when I seg-fault on a delete:
1) Make sure the memory is mine (do I know where the corresponding new is)?
2) Make sure I didn't delete the memory already (if I did, even if it WAS mine, it isn't now).
3) If you're pretty sure your seg-fault is caused by a single section of your code, break it out into a small test case in another project (kind of like you did in your question). Then play with it. If you had run your code examples up top in a small project you would have seen the seg-fault on the last one, and you would have noted the deletes worked in every other case. Breaking the code down like this would have let you know that you need to trace how you are storing these in your vector to see where you are losing ownership of them (via delete, or passing them to something that deletes them, etc...).
A side note: as others are saying, if you can use smart pointers do so, they will take care of the memory management for you. However, please continue your study here and understand how to use pointers that are dumb. There are times when you can not import boost, or have QT do your memory management for you. Also, there are times when you MUST store pointers in a container so don't be afraid to do that either (IE: QT developers STRONGLY suggest using pointers to store widgets instead of references or anything of the sort).
#include <vector>
using namespace std;
class Item
{
public:
int a;
};
int main()
{
vector<Item *> data;
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
for(int x = 0; x < 100; x++)
{
delete data.at(x);
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
while (!data.empty())
{
delete data.back();
data.pop_back();
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //worked for me, and makes sense
while (!data.empty())
{
delete data.at(0);
data.erase(data.begin());
}
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //This one fails, you are always trying to delete the 0th position in
// //data while never removing an element (you are trying to delete deleted memory)
// while (!data.empty())
// {
// delete data.at(0);
// }
return 0;
}

Either use a vector of smart pointers like this:
vector<shared_ptr<Item> > myVect;
Or use the Pointer Containers library in boost.
There may be a way to do this and re-use things, but it seems error-prone and a lot more work, especially considering Pointer Containers in boost is a header-only library.

use boost::shared_ptr<Item> and they will be deleted when the vector is cleared, or the element is deleted.

What do I do?
Don't maintain a vector of pointers. Really, it's almost always a mistake and you are fighting against the design of the vector (RAII) which takes care of memory management for you. You now have to call delete on every pointer.
Do you really need a vector of pointers? If you really do (not just think you do, but it is actually a requirement for one reason or another), then use smart pointers.
The vector will dynamically allocate memory for you, just use it as it was intended to be used.

It sounds as if you have the same pointer(s) repeated in your vector. To be sure you are only deleting them once just transfer them to a std::set and delete them there. For example,
std::set<Item*> s( items.begin(), items.end() );
items.clear();
while ( !s.empty() )
{
delete *s.begin();
s.erase( s.begin() );
}

Well, I did it. After a lot of time, a lot of aspirin, and a lot of lost hair, I finally figured out what the problem was. Turns out that I was calling a particular destructor earlier that contained the class which contained this vector of pointers. I had no idea that just calling a destructor would cause it to wipe all static data members. I hate c++ sometimes.

Related

Push_back method of vector of pointers causes crash C++

I'm trying to add pointers to a vector in C++. As such:
Puzzle * puzzleStart = new Puzzle();
std::vector<Puzzle*> OPEN;
OPEN.push_back(puzzleStart);
The first time a pointer is pushed, there is no problem. The second time, it causes a crash. I'm guessing the issue is the size of the vector, but I don't understand why. Is there anything more to this?
Update: You are right, the problem is elsewhere, I just realized that it occurs while I free the vector of pointer. There is another issue, if the vector contains dupplicates of pointers I think.
if (OPEN.size()!=0){
for (int i = 0; i < OPEN.size(); ++i) {
delete OPEN[i]; // Calls ~object and deallocates *tmp[i]
}
OPEN.clear();
}
How do i make sure that it doesn't try to erase allready deleted pointers?
You are right, the problem is elsewhere, I just realized that it occurs while I free the vector of pointer. There is another issue, if the vector contains dupplicates of pointers I think.
if (OPEN.size()!=0){
for (int i = 0; i < OPEN.size(); ++i) {
delete OPEN[i]; // Calls ~object and deallocates *tmp[i]
}
OPEN.clear();
}
How do i make sure that it doesn't try to erase allready deleted pointers?
If the problem is duplication of pointers, you should consider a container that does not allow duplication, such as a set. E.g.:
std::set<Puzzle*> s;
Puzzle *puzz = new Puzzle();
auto insert_result = s.insert(puzz);
if(!insert_result.second)
{
std::cout << "\"puzz\" was a duplication. No insertion made.\n";
}
// More items inserted into s, and used, etc.
for(auto p : s)
delete p;
s.clear();
When you delete the pointer, set it to nullptr. Deleting a null pointer does not cause a crash.

Use of pointer to vector which involved the use of 'new'

I would like to create a vector of pointers to struct
vector<myStruct*> vec
For elements in the vector, not all of them contain data. Some of them may point to NULL.
So, should I create space by new in each of the element first
for(int i = 0; vec.size() ;i++){
if (thisSpaceIsValid(i))
vec.at(i) = new myStruct;
else
vect.at(i) = NULL;
}
The problem comes:
-If I use new for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector(vec here)?
-If later I use delete to free the memory, would the problem of speed still bother me?
If I use "new" for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector("vec" here)?
You can do that.
Let's say the size of your vector is M and you only need N of those elements to have pointers to objects and other elements are null pointers. You can use:
myStruct* objects = new myStruct[N];
and then, use:
for(int i = 0, j = 0; vec.size(); i++)
{
if (thisSpaceIsValid(i))
{
if ( j == N )
{
// Error. Do something.
}
else
{
vec[i] = objects+j;
++j;
}
}
else
{
vect[i] = NULL;
}
}
You have to now make sure that you are able to keep track of the value of objeccts so you can safely deallocate the memory by using
delete [] objects;
PS
There might be a better and more elegant solution to your problem. It will be worth your while to spend a bit more time thinking over that.
EDIT:
After reading the question again, it seems I misunderstood the question. So here is an edited answer.
If you only need to execute the code during some kind of initialization phase, you can create all the instances of myStruct in an array and then just point to those from the vector as already proposed by R Sahu. Note that the solution requires you to create and delete all instances at the same time.
However, if you execute this code several times and/or don't know exactly how many myStruct instances you will need, you could overwrite new and delete for the struct and handle memory allocation yourself.
See Callling object constructor/destructor with a custom allocator for an example of this. See the answer by Jerry Coffin.
BTW - you don't need vec.at(i) as you are iterating from 0 to size. vec[i] is okay and should perform a better.
OLD ANSWER:
You can do
vector<myStruct*> vec(10000, nullptr);
to generate a vector with for instance 10000 elements all initialized to nullptr
After that you can fill the relevant elements with pointer to the struct.
For delete just
for (auto e : vec) delete e;
cause it is safe to do deleteon a nullptr
If you need a vector of pointers, and would like to avoid calling new, then firstly create a container of structs themselves, then assign pointers to the elements into your vec. Be careful with choosing the container of structs. If you use vector of structs, make sure to reserve all elements in advance, otherwise its elements may move to a different memory location when vector grows. Deque on the other hand guarantees its elements don't move.
Multiple small new and delete calls should be avoided if possible in c++ when performance matters a lot.
The more I think about it, the less I like #RSahu's solution. In particular, I feel memory management in this scenario would be a nightmare. Instead I suggest using a vector of unique_ptr's owning memory allocated via custom alloctor. I believe, sequential allocator would do.

creating an array of object pointers C++

I want to create an array that holds pointers to many object, but I don't know in advance the number of objects I'll hold, which means that I need to dynamically allocate memory for the array. I have thought of the next code:
ants = new *Ant[num_ants];
for (i=1;i<num_ants+1;i++)
{
ants[i-1] = new Ant();
}
where ants is defined as Ant **ants; and Ant is a class.
Will it work?
Will it work?
Yes.
However, if possible, you should use a vector:
#include <vector>
std::vector<Ant*> ants;
for (int i = 0; i < num_ants; ++i) {
ants.push_back(new Ant());
}
If you have to use a dynamically allocated array then I would prefer this syntax:
typedef Ant* AntPtr;
AntPtr * ants = new AntPtr[num_ants];
for (int i = 0; i < num_ants; ++i) {
ants[i] = new Ant();
}
But forget all that. The code still isn't any good since it requires manual memory management. To fix that you could to change your code to:
std::vector<std::unique_ptr<Ant>> ants;
for (auto i = 0; i != num_ants; ++i) {
ants.push_back(std::make_unique<Ant>());
}
And best of all would be simply this:
std::vector<Ant> ants(num_ants);
std::vector<Ant> ants(num_ants);
ants.resize(new_num_ants);
Yes that's the general idea. However, there are alternatives. Are you sure you need an array of pointers? An array of objects of class Ant may be sufficient. The you would only need to allocate the array:
Ant *ants = new Ant[num_ants];
In general, you should prefer using std::vector to using an array. A vector can grow as needed, and it will handle the memory management for you.
In the code you have posted, you would have to delete each element of ants in a loop, and then delete the array itself, delete [] ant. Keep in mind the difference between delete and delete [].
One more point, since array indices in C++ are 0-based, the following convention is used to iterate over the elements:
for (i=0; i<num_ants; i++)
{
ants[i] = new Ant();
}
This makes code much more readable.
Do you really need to hold pointers to the items? If you can use objects by value, a far simpler approach is to use a vector: std::vector<Ant> ants(num_ants);. Then not only do you not have to write looping, but you don't have to worry about memory leaks from raw pointers and other object management items.
If you need object pointers to say satisfy an API you can still use vector for the outer container and allocate the objects manually.
struct CreateAnt
{
Ant* operator()() const { return new Ant; }
};
std::vector<Ant*> ants(num_ants); // Create vector with null pointers.
std::generate(ants.begin(), ants.end(), CreateAnt());
std::vector<Ant*> ants( num_ants );
for ( int i = 0; i != num_ants; ++ i ) {
ants[i] = new Ant;
}
Or if you don't know how many in advance:
std::vector<Ant*> ants;
while ( moreAntsNeeded() ) {
ants.push_back( new Ant );
}
On the other hand, I think you need to ask yourself whether
Ant is an entity type or a value. If it's a value, you'll
probably want to skip the pointers and the dynamic allocation;
if it's an entity type, you'll have to consider the lifetime of
the object, and when and where it will be deleted.

Deleting an Array of Pointers - Am I doing it right?

I feel a little stupid for making a question about the deletion of pointers but I need to make sure I'm deleting in the correct way as I'm currently going through the debugging process of my program.
Basically I have a few arrays of pointers which are defined in my header file as follows:
AsteroidView *_asteroidView[16];
In a for loop I then initialise them:
for(int i = 0; i < 16; i++)
{
_asteroidView[i] = new AsteroidView();
}
Ok, so far so good, everything works fine.
When I eventually need to delete these in the destructor I use this code:
for(int i = 0; i < 16; i++)
{
delete _asteroidView[i];
}
Is this all I need to do? I feel like it is, but I'm worried about getting memory leaks.
Out of interest...
Is there much of a difference between an Array of Points to Objects compared with an Array of Objects?
This is correct. However, you may want to consider using Boost.PointerContainer, and save you hassle the hassle of manual resource management:
boost::ptr_vector<AsteroidView> _asteroidView;
for(int i = 0; i < 16; i++)
{
_asteroidView.push_back(new AsteroidView());
}
You do not have to manage the deletion, the container does that for you. This technique is called RAII, and you should learn about it if you want to have fun using C++ :)
About your edit: There are several difference, but I guess the most important are these:
An array of pointers can contain objects of different types, if these are subclasses of the array type.
An array of objects does not need any deletion, all objects are destroyed when the array is destroyed.
It's absolutely fine.
The rule of thumb is: match each call to new with an appropriate call to delete (and each call to new[] with a call to delete[])
Is this all I need to do? I feel like it is, but I'm worried about getting memory leaks.
Yes. The program is deallocating resources correctly. No memory leaks :)
If you are comfortable with using std::vector( infact it is easy ), it does the deallocation process when it goes out of scope. However, the type should be of -
std::vector<AsteroidView>
Given a class:
// this class has hidden data and no methods other than the constructor/destructor
// obviously it's not ready for prime time
class Foo {
int* bar_[16];
public:
Foo()
{
for (unsigned int i = 0; i < 16; ++i)
bar_[i] = new int;
}
~Foo()
{
for (unsigned int i= 0; i < 16; ++i)
delete bar_[i];
}
};
You won't leak memory if the constructor completes correctly. However, if new fails fails in the constructor (new throws a std::bad_alloc if you're out of memory), then the destructor is not run, and you will have a memory leak. If that bothers you, you will have to make the constructor exception safe (say, add a try ... catch block around the constructor, use RAII). Personally, I would just use the Boost Pointer Container if the elements in the array must be pointers, and a std::vector if not.

C++ std::vector of pointers deletion and segmentation faults

I have a vector of pointers to a class. I need to call their destructors and free their memory. Since they are vector of pointers vector.clear() does not do the job.So I went on to do it manually like so :
void Population::clearPool(std::vector<Chromosome*> a,int size)
{
Chromosome* c;
for(int j = 0 ;j < size-1;j++)
{
c = a.back();
a.pop_back();
delete c;
printf(" %d \n\r",j);
c = NULL;
}
}
The printf in there is since I have a talking destructor to see in which Chromosome the segmentation fault happens. When clearPool() is called and say we got a size of 100, it can give a segmentation fault in any Chromosome between 0 and 100.
I have no idea why this might be happening nor do I have a way to actually find what's wrong since while debugging with breakpoints all I see is that it happens in there at random chromosomes.
I am using codeblocks IDE and the gdb debugger. The stack trace when the segmentation fault happens has 4 memory addresses and a function wsncpy().
void Population::clearPool( std::vector <Chromosome*> & a )
{
for ( int i = 0; i < a.size(); i++ ) {
delete a[i];
}
a.clear();
}
Notice that the vector is passed by reference. In your code, a copy of the vector is used, which means that it is unchanged in the calling program. Because you delete the pointers in the copy, the pointers in the original are now all invalid - I suspect you are using those invalid pointers in some way not shown in the code you posted.
As a couple of template solutions have been posted that use C++ library algorithms, you might also want to consider a template solution that does not:
template <class C> void FreeClear( C & cntr ) {
for ( typename C::iterator it = cntr.begin();
it != cntr.end(); ++it ) {
delete * it;
}
cntr.clear();
}
Using this you can free any container of dynamically allocated objects:
vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );
Slight modified version compared to (#1800 INFORMATION).
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
I don't know why you are crashing, but I guess that one possibility is that the size of the vector is not the same as the size you are passing in. Also I notice you are iterating from 0 to size-2, do you not mean to go all the way to the end?
One way to delete all of the items in the array using idiomatic C++ is something like this:
template<class T>
class deleter
{
public:
void operator()(const T* it) const
{
delete it;
}
};
std::for_each(a.begin(), a.end(), deleter<Chromosome>());
Boost lambda already has a functor for deleting sequences of pointers, by the way:
std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
Are you sure that each pointer in the vector points to a different object?
(i.e. that two pointers don't both point to the same object, which you're trying to delete twice.
Are you sure that you don't delete some of the pointers before calling this method?
(i.e. are you sure that each pointer in the list points to a valid object?)
The most likely reason is calling delete twice for the same address. This can happen if you added one object more than once to the vector. To detect this insert some statement that will output the address of the object you will then delete.
printf( "will delete %d\n", (int)c );
delete c;
I found the problem.
It was in the most well hidden (by none other than stupid old me) place it could be.
As some might have guessed this is a genetic algorithms program. It is for a tutorial I am making. I was choosing the crossover points for the chromosomes randomly from a roulette wheel function which I made. Well ... inside there, there was a -1 which should not be there. That destroyed literally everything, and eventually lead to a segmentation fault.
Thank you all for your help, I saw some really good practises in this post which I intend to follow
I recommend to use smart pointer (ie:auto_ptr) instead of raw pointer and just use vector::clear method that will call the destructor for each element
void Population::clearPool(std::vector<Chromosome*>& a)
{
for(size_t i = 0; i < a.size(); i++) {
delete a[i];
}
a.clear();
}
It seems, that some pointers in your code do not reference correct Chromosome objects. This may happen, if you try to delete some objects twice as a result of code:
Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time
You may find useful ptr_vector from Boost Pointer Container Library in order to avoid similar errors