Удаление объекта в C++
Вот пример кода, который у меня есть:
void test()
{
Object1 *obj = new Object1();
.
.
.
delete obj;
}
Я запускаю его в Visual Studio, и он вылетает в строке "delete obj;". Разве это не нормальный способ освободить память, связанную с объектом? Я понял, что он автоматически вызывает деструктор... это нормально?
Вот фрагмент кода:
if(node->isleaf())
{
vector<string> vec = node->L;
vec.push_back(node->code);
sort(vec.begin(), vec.end());
Mesh* msh = loadLeaves(vec, node->code);
Simplification smp(msh);
smp.simplifyErrorBased(errorThreshold);
int meshFaceCount = msh->faces.size();
saveLeaves(vec, msh);
delete msh;
}
loadleaves()
это функция, которая читает сетку с диска и создает Mesh
объект и возвращает его.(думать о vec
а также node->code
это просто информация о файле, который нужно открыть)
Должен ли я удалить delete msh;
линия?
5 ответов
Разве это не нормальный способ освободить память, связанную с объектом?
Это распространенный способ управления динамически выделяемой памятью, но это не очень хороший способ сделать это. Этот вид кода является хрупким, потому что он не безопасен для исключений: если возникает исключение между тем, когда вы создаете объект и когда вы его удаляете, вы будете пропускать этот объект.
Гораздо лучше использовать контейнер интеллектуальных указателей, который можно использовать для управления ресурсами с привязкой к области действия (это чаще называется сбором ресурсов - инициализация или RAII).
В качестве примера автоматического управления ресурсами:
void test()
{
std::auto_ptr<Object1> obj1(new Object1);
} // The object is automatically deleted when the scope ends.
В зависимости от вашего варианта использования, auto_ptr
может не предоставить семантику, которая вам нужна. В этом случае вы можете рассмотреть возможность использования shared_ptr
,
Что касается того, почему ваша программа аварийно завершает работу, когда вы удаляете объект, вы не дали достаточного кода, чтобы кто-либо мог с уверенностью ответить на этот вопрос.
Ваш код действительно использует нормальный способ создания и удаления динамического объекта. Да, это совершенно нормально (и действительно гарантировано стандартом языка!), Что delete
вызовет деструктор объекта, так же, как new
должен вызвать конструктор.
Если бы вы не были экземпляром Object1
напрямую, но подкласс, напомню, что любой класс, от которого предполагается наследовать, должен иметь виртуальный деструктор (так, чтобы деструктор правильного подкласса мог быть вызван в случаях, аналогичных этому) - но если ваш пример кода действительно репрезентативным для вашего действительного кода, это не может быть вашей текущей проблемой - должно быть что-то другое, возможно, в коде деструктора, который вы нам не показываете, или какое-то повреждение кучи в коде, который вы не показываете в этой функции или в тех это звонит...?
Кстати, если вы всегда собираетесь удалять объект непосредственно перед выходом из функции, которая его создает, нет смысла делать этот объект динамическим - просто объявите его как локальный (класс хранилища) auto
, как по умолчанию) переменная указанной функции!
Просто обновление ответа Джеймса.
Разве это не нормальный способ освободить память, связанную с объектом?
Да. Это нормальный способ освободить память. Но оператор new/delete всегда приводит к проблеме утечки памяти.
Начиная с C++17 уже удален auto_ptr auto_ptr. Я предлагаю shared_ptr или unique_ptr для решения проблем с памятью.
void test()
{
std::shared_ptr<Object1> obj1(new Object1);
} // The object is automatically deleted when the scope ends or reference counting reduces to 0.
- Причина удаления auto_ptr заключается в том, что auto_ptr нестабилен в случае семантики копирования.
- Если вы уверены, что во время осциллографа ничего не произойдет, предлагается unique_ptr.
- Если между указателями есть круговая ссылка, я предлагаю взглянуть на weak_ptr.
Если он падает на delete
линия то у вас почти наверняка как-то испортилась куча. Нам нужно больше кода, чтобы диагностировать проблему, так как в приведенном вами примере нет ошибок.
Возможно, у вас есть переполнение буфера в куче, которое повредило структуры кучи или даже что-то такое же простое, как "double free" (или в случае C++ "double delete").
Кроме того, как отметил Fuzz, в деструкторе также может быть ошибка.
И да, это совершенно нормально и ожидается для delete
вызвать деструктор, что фактически является одной из двух его целей (вызвать деструктор, а затем освободить память).
saveLeaves(vec,msh);
Я предполагаю, что берет msh
указатель и помещает его в vec
, поскольку msh
это просто указатель на память, если вы удалите его, он также будет удален внутри вектора.