Это утечка памяти? - PullRequest
       15

Это утечка памяти?

13 голосов
/ 18 мая 2010
char *pointer1;
char *pointer2;

pointer1 = new char[256];
pointer2 = pointer1;

delete [] pointer1;

Другими словами, должен ли я также делать delete [] pointer2?

Спасибо!

Ответы [ 11 ]

17 голосов
/ 18 мая 2010

Нет, этот код в порядке и не пропускает память.

Вы должны использовать delete [] только один раз, потому что вы использовали только один новый, чтобы выделить область для памяти, даже если есть две указатели на ту же самую память.

7 голосов
/ 18 мая 2010

Простое правило: вам нужно столько delete с, сколько new с. Еще лучше, используйте что-то вроде умного указателя или контейнера, чтобы позаботиться об этом за вас.

И еще один незначительный момент: pointer2 становится «висящим указателем», когда вы звоните delete на pointer1.

4 голосов
/ 18 мая 2010

Это не утечка, но это напрашивается на неприятности. pointer2 указывает на то, кто знает что, как только вы удалите pointer1. Это то, что называется «висячий указатель». Его использование в лучшем случае может привести к segfault, а в худшем - к таинственному искажению данных во всем, что в итоге выделит то же место.

2 голосов
/ 18 мая 2010

Кроме того, рассмотрите возможность использования boost::shared_ptr<> из библиотек Boost. Это величайшая вещь со времен нарезанного хлеба.

typedef boost::shared_ptr<TypeX> StrRef;

foo() {
  StrRef pointer1(new TypeX);

  while(something) {
    StrRef pointer2 = pointer1;
    // do stuff
  }

 return;
}

Данные (TypeX) будут удалены, когда последний указатель на них выйдет из области видимости. Вы можете сделать что-то подобное со встроенным типом auto_ptr<>, если вам не нужен счетчик ссылок:

typedef auto_ptr<TypeX> StrRef;

foo() {
  StrRef pointer1(new TypeX);

  while(something) {
    TypeX * pointer2 = pointer1.get();
    subroutine(pointer2);
    if (condition) return;
  }

 return;
}

Всякий раз, когда pointer1 выходит из области видимости, он удаляет данные. Преимущество этого заключается в том, что вам не нужно помнить, что вы должны поместить delete перед оператором return внизу, и если pointer1 выходит из области видимости по какой-либо другой причине (т.е. возврат из середины цикла или subroutine() выдает исключение, тогда данные все равно будут правильно освобождены.

Я не проверял этот код, поэтому вам придется самостоятельно проверять документы на auto_ptr<> и boost::shared_ptr<>.

Я настоятельно рекомендую максимально использовать библиотеки Boost. Это написано профессионалами, это в основном промежуточная область для расширений до C ++.

2 голосов
/ 18 мая 2010

Хотя это не приводит к утечке памяти, если вы хотите быть явным, вы должны установить для point1 и point2 значение NULL (и инициализировать их таким же образом).

1 голос
/ 18 мая 2010

delete удаляет память, выделенную new. Поскольку у вас есть только один new, вам нужен только один delete.

0 голосов
/ 18 мая 2010

Вот пробел в вашем мышлении: вы не удаляете указатели - вы удаляете память. Вы просто используете указатель, чтобы идентифицировать блок памяти, который нужно освободить. Поскольку две переменные указывают на одну и ту же память, удаление одной точно равнозначно удалению другой. Другими словами, удаление обоих равнозначно удалению одного из них дважды - что, очевидно, неправильно.

0 голосов
/ 18 мая 2010

Здесь вы просто скажете, что блок памяти, выделенный new char[256], будет указывать на pointer1 и pointer2 одновременно.

Было бы утечкой памяти, если бы вы написали delete[] pointer2; оператор после.

0 голосов
/ 18 мая 2010

Каждый new должен иметь один и только один, соответствующий delete. Если вы удалите другой указатель, вы нарушите это правило.

0 голосов
/ 18 мая 2010

Нет, вам не нужно удалять [] pointer2, потому что вы не выделили для него память!

Оператор pointer2 = pointer1 заставляет pointer2 указывать на тот же адрес памяти, что и pointer1, не выделяет для него никакой дополнительной памяти.

...