Preventing double deletion of pointers

I had vector<Points*> points;

( size: 6

with all unique Points

) in my program in which I repeated points to draw something on the screen. However, according to my new requirements, I would increase the length of the vector to size: 14

.

The new items to be added had to be from the previous one 6

Points

, so instead of allocating new memory, I thought to just use the previous pointers like this:

while (currentSize < 14){
  int rndPoint = getRandomPoint(0, 5); //random index to choose from the vector
  points->push_back(points[randPoint]);
}

      

In the destructor of a class, when I have to free memory, I do the following:

for(int i=0;i<points.size(); ++i){
  if(points[i] != NULL){
    delete (points[i]);
  }
}

      

However, when I try to exit the program - I get an access violation error in a loop (especially when it i

reaches the index 6

). When I already removed 6 unique points with delete

, why does the condition if (points[i] != NULL)

result in true

for i=6,7...13

?

+3


source to share


3 answers


Use a smart pointer. If your program source contains delete

, and it is not in smart pointer delete, your program is broken. (And why the hell would you do this instead std::default_deleter

?).

Winner of the "Best Smart Pointer Award 2014" std::unique_ptr

, with an honorable mention for std::shared_ptr

when you just have to copy a pointer.



The rule of zero means that you hardly ever need to implement the / etc destructor yourself, as you should always use generic resource management classes to manage it yourself.

+7


source


The reason is that when removed, other references to the same memory are not set to nullptr

(or 0, pre C ++ 11). Consider:

int *foo = new int;
// foo should be non-nullptr now
int *bar = foo;
// bar should be non-nullptr now
delete foo;
// both foo and bar are still non-nullptr.

      



There are three ways to solve your specific problem:

  • Use std::shared_ptr

  • You have a separate one std::vector

    for unique instances:

    std::vector<Point> unique_points;
    std::vector<Point*> used_points;
    
    // create all needed points *once* in unique_points
    // insert pointers to the points in unique_points into used_points
    
          

  • Just make copies.

+4


source


The general answer is that when you use dynamic memory, you have a PLAN to clean up.

One plan is to use various forms of standard library template pointers (as described above). However, there are other ways to do this.

The "best" plan depends on the type of application. For example, when you use some graph structures, reference counting may not work if this method works with other types of structures.

For example, if you try to do reference counting when you have

A points to B.
B points to C and D
C and D points to E
E points to B

      

This gives the following reference counts

B 2 C 1 D 1 E 2

Destroying the A-> B link gives these link counts

B 1 C 1 D 1 E 2

without a struct reference, so it will never be deleted.

Choose the best plan for your situation.

0


source







All Articles