Ankit Sharma
Ankit Sharma

Reputation: 663

What if I delete an array once in C++, but allocate it multiple times?

Suppose I have the following snippet.

int main()
{
    int num;
    int* cost;
    while(cin >> num)
    {
        int sum = 0;
        if (num == 0)
          break;

        // Dynamically allocate the array and set to all zeros
        cost = new int [num];
        memset(cost, 0, num);
        for (int i = 0; i < num; i++)
        {
            cin >> cost[i];
            sum += cost[i];
        }
        cout << sum/num;
    }
`  `delete[] cost;
    return 0;
}

Although I can move the delete statement inside the while loop for my code, for understanding purposes, I want to know what happens with the code as it's written. Does C++ allocate different memory spaces each time I use operator new?

Does operator delete only delete the last allocated cost array?

Upvotes: 20

Views: 1656

Answers (6)

Mike Seymour
Mike Seymour

Reputation: 254461

Does C++ allocate different memory spaces each time I use operator new?

Yes.

Does operator delete only delete the last allocated cost array?

Yes.

You've lost the only pointers to the others, so they are irrevocably leaked. To avoid this problem, don't juggle pointers, but use RAII to manage dynamic resources automatically. std::vector would be perfect here (if you actually needed an array at all; your example could just keep reading and re-using a single int).

Upvotes: 22

AnT stands with Russia
AnT stands with Russia

Reputation: 320481

There is no cost array in your code. In your code cost is a pointer, not an array.

The actual arrays in your code are created by repetitive new int [num] calls. Each call to new creates a new, independent, nameless array object that lives somewhere in dynamic memory. The new array, once created by new[], is accessible through cost pointer. Since the array is nameless, that cost pointer is the only link you have that leads to that nameless array created by new[]. You have no other means to access that nameless array.

And every time you do that cost = new int [num] in your cycle, you are creating a completely new, different array, breaking the link from cost to the previous array and making cost to point to the new one.

Since cost was your only link to the old array, that old array becomes inaccessible. Access to that old array is lost forever. It is becomes a memory leak.

As you correctly stated it yourself, your delete[] expression only deallocates the last array - the one cost ends up pointing to in the end. Of course, this is only true if your code ever executes the cost = new int [num] line. Note that your cycle might terminate without doing a single allocation, in which case you will apply delete[] to an uninitialized (garbage) pointer.

Upvotes: 5

Mike Robinson
Mike Robinson

Reputation: 8945

I strongly advise you not to use "C idioms" in a C++ program. Let the std library work for you: that's why it's there. If you want "an array (vector) of n integers," then that's what std::vector is all about, and it "comes with batteries included." You don't have to monkey-around with things such as "setting a maximum size" or "setting it to zero." You simply work with "this thing," whose inner workings you do not [have to ...] care about, knowing that it has already been thoroughly designed and tested.

Furthermore, when you do this, you're working within C++'s existing framework for memory-management. In particular, you're not doing anything "out-of-band" within your own application "that the standard library doesn't know about, and which might (!!) it up."

C++ gives you a very comprehensive library of fast, efficient, robust, well-tested functionality. Leverage it.

Upvotes: 6

Steve
Steve

Reputation: 1810

First off this line is wrong:

memset(cost, 0, num);

It assumes an int is only one char long. More typically it's four. You should use something like this if you want to use memset to initialise the array:

memset(cost, 0, num*sizeof(*cost));

Or better yet dump the memset and use this when you allocate the memory:

cost = new int[num]();

As others have pointed out the delete is incorrectly placed and will leak all memory allocated by its corresponding new except for the last. Move it into the loop.

Upvotes: 3

JBL
JBL

Reputation: 12907

Yes. So you get a memory leak for each iteration of the loop except the last one.

When you use new, you allocate a new chunk of memory. Assigning the result of the new to a pointer just changes what this pointer points at. It doesn't automatically release the memory this pointer was referencing before (if there was any).

Upvotes: 3

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70929

Every time you allocate new memory for the array, the memory that has been previously allocated is leaked. As a rule of thumb you need to free memory as many times as you have allocated.

Upvotes: 1

Related Questions