C ++: утечки памяти - PullRequest
4 голосов
/ 16 июля 2009

Вопрос: при каком значении переменной n следующий код вызовет утечки памяти?

Это код:


int* Bar(int n)
{
  if (n == 1)
    throw "exception";
  return new int[n];
}

void Foo(int n)
{
  int *a = Bar(n);
  if (n <= 2)
    return;
  delete[] a;
}

От 5.3.4 / 7

Когда значение выражения в прямой новый декларатор равен нулю, функция распределения вызывается выделить массив без элементов.

От 3.7.3.1/2

Эффект разыменования указателя возвращается как запрос на нулевой размер не определено.

Также

Даже если размер пространства запрошенный [по новой] равен нулю, запрос может потерпеть неудачу.

Это означает, что вы можете сделать это, но вы можете не юридически (в четко определенной форме на всех платформах) память, которую вы получаете - вы можете только передать его на удаление массива - и вы следует удалить его.

Вот интересное примечание (т. Е. не является нормативной частью стандарта, но включены для пояснительных высказываний) прилагается к предложению от 3.7.3.1/2

* 1 034 * [32. Цель состоит в том, чтобы иметь оператора new () реализуется путем вызова malloc () или calloc (), поэтому правила по существу то же самое. С ++ отличается от C в требовании нулевого запроса вернуть ненулевой указатель.]
  • И если n равно 1, мы получаем:

int * a = Bar (1) и Bar (1) выдает исключение. Будет ли это исключение в конструкторе переменной a? И не вызовет ли это утечки памяти?

Ответы [ 6 ]

7 голосов
/ 16 июля 2009

Это может вызвать их, если == 0 или == 2.

Если == 1, генерируется исключение и не выделяется память. Если> 2 памяти выделены и освобождены.

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

Если == 2 памяти выделена и функция возвращается. Это очевидная утечка.

2 голосов
/ 16 июля 2009
If n < 0            you'll more likely get exception std::bad_alloc (because of n will be converted to size_t which is unsigned) - no memory leak.
If n == 1           you'll get exception (invoked by `throw "exception"`) - no memory leak.
If n == 0 || n == 2 you'll never call delete - memory leak.
If n > 2            you'll call delete - no memory leak.
0 голосов
/ 15 августа 2016

Да, с 0 и 2 вы получите утечки памяти.


Также это очень плохая практика для управления такой динамической памятью. На C ++ это гораздо более естественный / лучший способ создать класс, который будет управлять памятью (например, в конструкторе он выделяет некоторую память, а в деструкторе - освобождает). Это было бы более без утечек и безопаснее

0 голосов
/ 16 июля 2009

Так как нет никакого ловца к сгенерированному исключению, он продолжится и возвратится. Но так как мы объявили как целочисленный указатель, если вы отправите 'n' как ноль, будет создан указатель по умолчанию. Вы также можете проверить размер указателя. Но это не приведет к утечке памяти. Причина в том, что когда вы делаете возврат, так как он является целочисленным указателем и является локальной переменной, занятая память будет освобождена по умолчанию. Таким образом, в упомянутом вами случае не будет утечки памяти.

0 голосов
/ 16 июля 2009

Ваша оценка в основном верна - n = 2 приведет к утечке памяти, n = 0 теоретически приведет к утечке памяти - n = 1 вызовет исключение (поэтому новый int никогда не будет выполнен), поэтому утечки памяти нет.

Любое значение для n> 2 НЕ приведет к утечке памяти.

Теперь, если n <0 - у вас неопределенное поведение - и вы можете получить утечку памяти (то есть отрицательное целое число может быть преобразовано в большое положительное значение без знака - и могут случиться плохие вещи) </p>

0 голосов
/ 16 июля 2009

Нет, если я правильно понимаю ваш вопрос, функция bar сгенерирует исключение, и функция Foo фактически никогда не перехватит его, что означает, что оно также будет передаваться из этой функции. Но нет, это не должно вызывать утечки памяти, потому что вы выбрасываете до того, как выделение будет сделано.

...