Это неправильно использовать auto_ptr с новым символом [n] - PullRequest
14 голосов
/ 04 ноября 2008

Если я объявляю временный автоматически удаленный буфер символов, используя

std::auto_ptr<char> buffer(new char[n]);

тогда буфер автоматически удаляется, когда буфер выходит из области видимости. Я бы предположил, что буфер удаляется с помощью delete.

Однако буфер был создан с использованием new [], и поэтому строго говоря буфер должен быть удален с помощью delete [].

Какова вероятность того, что это несоответствие может привести к утечке памяти?

Ответы [ 8 ]

19 голосов
/ 04 ноября 2008

Поведение вызова delete для указателя, выделенного с помощью new [], равно undefined . Как вы и предполагали, auto_ptr вызывает delete , когда умный указатель выходит из области видимости. Вам нужно беспокоиться не только об утечках памяти - возможны сбои и другие странные действия.

Если вам не нужно передавать владение указателем, вам может подойти класс Boost scoped_array .

10 голосов
/ 04 ноября 2008

Я бы использовал вектор char в качестве буфера.

std::vector<char>    buffer(size);

read(input,&buffer[0],size);

По сути, вы даже не хотите звонить новым, если вам это не нужно.
Вектор предоставляет размерный буфер времени выполнения, который вы можете использовать как массив (буфер).

Самое приятное то, что вектор очищается после себя, и стандарт гарантирует, что все элементы в векторе будут находиться в хранилище. Идеально подходит для буфера.

Или, более того, гарантия:

(&buffer[0]) + size == (&buffer[size])
7 голосов
/ 04 ноября 2008

Это приводит к неопределенному поведению (может быть хуже, чем утечка памяти, например, повреждение кучи), вместо этого попробуйте boost's scoped_array или shared_array .

6 голосов
/ 04 ноября 2008

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

Тем не менее, поскольку это поведение не определено, я настоятельно рекомендую использовать std::vector<char> или boost::scoped_array<char> / boost::shared_array<char>. Все это вполне жизнеспособные и превосходные варианты использования std::auto_ptr<> в этом случае. Если вы используете std::vector, у вас также есть возможность динамически увеличивать буфер при необходимости.

5 голосов
/ 04 ноября 2008

Есть ли веская причина не использовать std :: string? std :: vector, как другие предложили? То, что вы делаете, неправильно, но не зная, что вы пытаетесь сделать, рекомендовать что-то еще сложно.

4 голосов
/ 10 ноября 2008

Да, это неправильно. Заворачивать в тривиальную обертку.

typedef< typename T_ >
struct auto_vec{
  T_* t_;
  auto_vec( T_* t ): t_( t ) {}
  ~auto_vec() { delete[] t_; }
  T_* get() const { return t_; }
  T_* operator->() const { return get(); }
  T_& operator*() const { return *get(); }
  /* you should also define operator=, reset and release, if you plan to use them */
}

auto_vec<char> buffer( new char[n] );
2 голосов
/ 17 июля 2012

Прошло несколько лет с тех пор, как был задан вопрос.

Но я попал на эту страницу в результате поиска, поэтому я решил, что я мог бы также отметить: std :: unique_ptr , замена auto_ptr в C ++ 11, может обрабатывать удаление объектов, созданных с помощью нового [].

Существует две версии std :: unique_ptr: 1) Управляет временем жизни один объект (например, выделенный с новым) 2) Управляет временем жизни динамически размещенный массив объектов (например, выделенный с помощью нового [])

cppreference unique_ptr

0 голосов
/ 04 ноября 2008

Это кажется ужасно сложным для очень простого решения. Что не так с вами, используя

 char *c=new char[n] 

здесь, а затем удалить? Или, если вам нужно более динамичное решение,

vector<char> c

Бритва Оккама, чувак. : -)

...