-1

I have a vector of pointers like so: vector<Operators*> valid_start = {&negative, &values, &numbers, &bracket_left, &functions}; When using the following code to deallocate the memory, the program crashes

void deallocate_vector(vector<Operators*> & a)
{
    for(int it = 0; it < a.size(); it++)
    {
        delete a[it];
    }
    a.clear();
}

I've looked at these threads

Does vector::erase() on a vector of object pointers destroy the object itself?

clearing a vector of pointers

Cleaning up an STL list/vector of pointers

Deallocating objects stored in a vector?

and cannot see why this code fails. I've tried this form of deallocation as well, and this also crashes:

for (std::vector<Operators*>::iterator it = a.begin(); it != a.end(); ++it)
{
     delete(*it);
} 
a.clear();

I have effectively copied code verbatim, and it still fails. Why?

EDIT:

The declaration of negative. The rest of the pointers are of the same type

struct Operators
{
    std::vector<std::string> members;
    std::vector<Operators*> precedents;
    std::vector<Operators*> followers;
}negative;

negative.members = {"-"};
negative.precedents = {&basic_operators, &values, &numbers, &comma, &bracket_left, &bracket_right, &factorial};
negative.followers = {&bracket_left, &numbers, &values, &functions};
Community
  • 1
  • 1
Utumno
  • 19
  • 5
  • 4
    You need to post an [mcve]. From the first line of code it looks like you are storing pointers to stack objects. You cannot call delete on those. We need more information to confirm that though. – NathanOliver Sep 29 '16 at 17:51
  • If `negative`, ..., `functions` are allocated on the stack, it is normal that such a crash occurs. `delete` should only be used on heap allocated variables. Can we see the declaration of negative ? – Franck Sep 29 '16 at 17:51
  • 1
    You only `delete` pointers returned from `new`. If the pointers stored in your vector were not, don't call `delete` on them. That's the pedantic answer, but also: in modern C++ you never* call `delete` or `new` directly - you should use `unique_ptr` and `make_unique`, `shared_ptr` and `make_shared` (*never has some exceptions) – David Sep 29 '16 at 17:55
  • @David If the pointers are not returned from `new`, do you not need to deallocate? – Utumno Sep 29 '16 at 17:59
  • @Utumno Correct. If you write `int x; int* p = &x;` nothing has been allocated. There is no need to deallocate. If you try to deallocate `p`, you'll crash, because `p` points to a variable on the stack, not a heap allocation. – David Sep 29 '16 at 18:00
  • @David Thanks, I didn't know that (obviously). – Utumno Sep 29 '16 at 18:02
  • Terminology niggle: Prefer automatic and dynamic over stack and heap to show respect to systems that have no stacks or heaps. – user4581301 Sep 29 '16 at 19:18

1 Answers1

2

This is exactly why you should be weary of using & outside very controlled circumstances.

I am not sure what an Operator is, presumably some class, so I will give a similar example with a type that is universally understood and explain it. Consider:

{ // Some sort of local scope
    int x = 10;
    int* xp = &x;
}

The life-cycle of x is controlled by the compiler. It exists "on the stack", within the execution frame of the program when it enters local scope. It is created when scope is opened/when it is declared, and is deleted when the scope exits. Note that compiler implementation details might mean it is actually created/deleted at different times (or even never, if it is never used), but you can assume that behavior for the most part.

Now, xp is a pointer to x. What do you think happens if I delete xp and then the compiler deletes the memory behind x? The same memory is deleted twice - which is undefined behavior that tends to lead to crashes or worse.

For the purpose of understanding the problem, you might think of this as if it were:

{
    int* __x = new int;
    int& x = (*__x);
    /////////////////

    x = 10;
    int* xp = &x;
    // now xp == __x

    /////////////////
    delete __x;
}

Note this is not actually what the compiler will do; however, this somewhat illustrates the outward behavior of what it actually does.