Это неправильно использовать auto_ptr с новым символом [n]

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

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

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

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

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

8 ответов

Решение

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

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

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

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

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

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

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

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

(&buffer[0]) + size == (&buffer[size])

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

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

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

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

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

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] );

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

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

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

http://en.cppreference.com/w/cpp/memory/unique_ptr

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

 char *c=new char[n] 

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

vector<char> c

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

Другие вопросы по тегам