4

How to delete an array declared with new if I don't have access to the original pointer x? Let's assume, I know the array size.

For example, if I write the following code:

void enlarge(int * x) {
    int * tmp = new int[20];
    memcpy(tmp, x, 10*sizeof(int));
    delete[] x; //?
    x = tmp;
}

int main() {
    int * x = new int[10];
    enlarge(x);
    delete[] x; //??? free(): double free detected in tcache 2
}
  1. Would delete[] within enlarge() function know how much memory to free?
  2. Apparently, delete[] within main() results in an error during execution. Why? How to avoid it?
6
  • 1
    enlarge should probably return a new pointer, and then can be called as x = enlarge(x). Otherwise, you are deleting old memory and leaking new. The caller can no longer access either. Better still, do yourself a favor and use std::vector<int> Commented May 7, 2023 at 21:28
  • Yes, it does. Preferrably you'd leave freeing the data to a smart pointer though: void enlarge(std::unique_ptr<int[]> & x) { auto tmp = std::make_unique<int[]>(20); memcpy(tmp.get(), x, 10 * sizeof(int)); x = std::move(tmp); } int main() {auto x = std::make_unique<int[]>(10); enlarge(x);} Commented May 7, 2023 at 21:28
  • 3
    Apparently, delete[] within main() results in an error during execution. Why? How to avoid it? Because you pass x by value. void enlarge(int * x) { copies x and enlarges it freeing the original memory location but not changing x in main which after running enlarge x in int main() points to the original location which you attempt to free a second time in int main() Commented May 7, 2023 at 21:29
  • 5
    Incidentally, the concept of array decay is irrelevant here. It doesn’t happen in your code anyway: all variables you declare of pointer, not array, type. Commented May 7, 2023 at 21:34
  • 1
    @user1079505 "Do you mean that array decay refers only to arrays declared statically, e.g. with int x[10]?" -- Inaccurate. Array decay occurs only when you have an object whose type is an array. If you declare int x[10] then the type of x is an array. If you declare int * x then the type of x is a pointer. A pointer cannot be subject to the decay from an array to a pointer because 1) a pointer is not an array and 2) a pointer is already a pointer. Commented May 7, 2023 at 22:42

3 Answers 3

2

The function enlarge produces a memory leak because the pointer x declared in main is passed to the function by value. That is the function deals with a copy of the value of the original pointer x. Changing within the function the copy leaves the original pointer x declared in main unchanged.

As a result this statement in main

delete[] x;

invokes undefined behavior because the memory pointed to by the pointer x was already freed in the function enlarge.

You need to pass the pointer by reference like

void enlarge(int * &x) {
    int * tmp = new int[20];
    memcpy(tmp, x, 10*sizeof(int));
    delete[] x;
    x = tmp;
}

Pay attention to that instead of raw pointers it is better to use standard container std::vector.

Sign up to request clarification or add additional context in comments.

Comments

2

How to delete an array declared with new if I don't have access to the original pointer x?

You cannot. In order to delete a dynamic array, you must know the pointer to the first element of that array - i.e. the pointer that was returned by new.

Would delete[] within enlarge() function know how much memory to free?

Yes.

Apparently, delete[] within main() results in an error during execution. Why?

Because the same pointer was already deleted in enlarge. If you delete a pointer more than once, the behaviour of the program is undefined.

How to avoid it?

Don't delete a pointer more than once.

P.S. enlarge leaks the array that it allocates. Don't use new and delete. Use RAII containers such as std::vector instead.


Ah, so array decay affects only statically declared arrays

Array decay is an implicit conversion of an expression of array type to a pointer to first element. The type of x is int*. That is not an array type. int* is a pointer type. As it isn't an array type, it doesn't implicitly convert to a pointer to first element. x is already the pointer to the first element.

1 Comment

Ah, so array decay affects only statically declared arrays, and the dynamically declared ones can be always deleted with delete[], for as long as I have some pointer to the first element?
1

The delete call within enlarge is deleting the int *x declared in main, as you're simply passing the pointer to a new function. This is why delete[] x in main gives you a double free; that pointer doesn't exist anymore.

Update: I should clarify that when you pass a pointer by value, you're effectively copying it. deleteing a copy of a pointer also deletes the original pointer.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.