2015-06-13 2 views
1

Если у меня есть:Что удалить после назначения?

template<> 
char *toBytes<uint64_t>(uint64_t src) { 
    char *data = new char[8]; 
    //...stuff 
    return data; 
} 

template<> 
void write<uint64_t>(char *dst, uint64_t src) { 
    char *srcBytes = toBytes(src); 
    for (int i = 0; i < 8; ++i) { 
    *(dst++) = *(srcBytes++); //am I leaking here? 
    } 
} 

, который получает называется что-то вроде:

char *keyPtr = new char[27]; 
//...stuff 
write(keyPtr, 1234ull); 
//...write up to 27 

Если бы delete[] keyPtr; бы я удалил srcBytes? Я думаю, что вопрос заключается в том, что на линии, спрашивающей, не просачивается ли я, это то, что делает копию, и в результате удаление keyPtr оставляет srcBytes еще не удаленным?

Все еще изучая C++, и это не всегда понятно для меня, когда конструктор копирования называется vs оператором присваивания.

EDIT 1:

Исправлено удаление в соответствии с @ ответ Steephen в

EDIT 2

Добавить toBytes согласно @ WhozCraig замечании

+0

Нет, удаление 'keyPtr' не имеет никакого отношения к управлению памятью, переданной' srcBytes'. И так как мы не можем видеть, как возникла эта память (источник для 'toBytes' не включен в ваш вопрос), мы не можем сказать, требуется ли удаление' srcBytes' или нет. Если он динамически распределен, ему необходимо удалить, но обратите внимание, что вы потеряете начальный адрес выделения с помощью этой конструкции цикла, которая постоянно увеличивает значение srcBytes', поэтому вам нужно будет сохранить указатель на него, чтобы удалить [] ' или использовать другой механик цикла. – WhozCraig

+0

С вашим добавлением вам обязательно нужно удалить этот возвращенный буфер из 'toBytes()'. Проблема в том, что единственный указатель, который ссылается на него, изменяется сразу после его назначения. То есть вы теряете указатель, который вам нужно удалить [] '. Может, подумать об этом. – WhozCraig

+0

В качестве побочного примечания, поскольку вы все больше узнаете о языках C++ и других языках, одна проблема дизайна начинает входить в игру с точки зрения управления жизненным циклом и передачи владения динамической памятью в целом. Используются различные методологии, включая пулы памяти (обычно используемые w/Objective C) или общие указатели (найдены в таких вещах, как библиотека ускорения). Это помогает передать понятию пользователям API, что эта память управляется, хотя и с некоторыми издержками производительности (например, счетчиками ссылок и т. Д.), – Gary

ответ

1

У вас есть утечка памяти. Нет, delete []-keyPtr не имеет ничего общего с srcBytes, независимым распределением. Два адресованных буфера не связаны (за исключением контента из-за вашего кода-копии).

Помимо очевидного (с использованием std::vector<> и позволяя RAII взять на себя управление памятью для всего этого), достаточно минимального изменения кода, чтобы заткнуть течь будет петля что-то вроде этого:

template<> 
void write<uint64_t>(char *dst, uint64_t src) 
{ 
    char *srcBytes = toBytes(src); 
    std::copy(srcBytes, srcBytes+8, dst); 
    delete [] srcBytes; 
} 

или с помощью смарт-указатель:

template<> 
void write<uint64_t>(char *dst, uint64_t src) 
{ 
    std::unique_ptr<char[]> srcBytes(toBytes(src)); 
    std::copy(srcBytes.get(), srcBytes.get()+8, dst); 
} 

Оба используют фондовый алгоритм std::copy, который и выполняет то, что вы, кажется, хотите, сохраняя при этом оригинальный результат toBytes для правильного Клио NUP. Который вы выбираете (или, возможно, что-то совершенно другое), я оставляю вам.

Удачи.

3

Вы должны использовать

delete [] keyPtr; 

вместо звонка delete более для цикла;

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

Я думаю, что вопрос, на линии с просьбой, если я утечка, является то, что делает копию, и в результате удаляемого keyPtr листья srcBytes

Если программа выделена память для srcBytes использования новый оператор, вы должны удалить его так же, как и для keyPtr. Поскольку обработка ресурсов обоими указателями независима даже после вашего назначения в вашем случае.

1

Вот несколько случаев, когда вы утечка памяти, где вы использовали «новый»:

  • Функция работает вне области, прежде чем вы могли бы удалить его и нет никакого указателя на выделенную память за пределами функция.
  • Вы забыли удалить в случае необходимости
  • Вы смешиваете delete и delete []
  • Исключение зажат между использованием «новых» и «удалить».

Даже в качестве новичков неплохо ознакомиться с умными указателями.

Смежные вопросы