Объект C ++, созданный с помощью new, уничтоженный с помощью free (); Насколько это плохо? - PullRequest
34 голосов
/ 31 октября 2010

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

Однако, если кто-то создает объект:

Packet* thePacket = new Packet();

Делает ли этонезависимо от того, уничтожается ли is с помощью delete thePacket; или free(thePacket);?

Я понимаю, что delete вызывает деструктор, в то время как free () нет, но Packet не имеет деструктора.У меня ужасное время, застрявшее в болоте управления памятью, и я думаю, что это может быть одной из многих проблем.

Ответы [ 6 ]

50 голосов
/ 31 октября 2010

Да, это имеет значение.

Для памяти, полученной с использованием new, вы должны использовать delete.

Для памяти, полученной с использованием malloc, вы должны использовать free.

new и malloc могут внутренне использовать разные структуры данных для отслеживания того, что и где выделено памяти.Таким образом, чтобы освободить память, вы должны вызвать соответствующую функцию, которая знает об этих структурах данных.Однако, как правило, плохая идея смешивать эти два типа распределения памяти в части кода.

27 голосов
/ 31 октября 2010

Если вы позвоните free(), деструктор не будет вызван.

Кроме того, нет гарантии, что new и free работают в одной и той же куче.

Вы также можете переопределить new и delete, чтобы работать специально с определенным классом. Если вы сделаете это, но вызовете free() вместо пользовательского delete, то вы пропустите любое особое поведение, которое вы написали в delete. (Но вы, вероятно, не задавали бы этот вопрос, если бы сделали это, потому что вы знали бы, какое поведение вам не хватало ..)

6 голосов
/ 31 октября 2010

Packet имеет деструктор, даже если вы явно не объявили его. У него есть деструктор по умолчанию. Деструктор по умолчанию, вероятно, на самом деле ничего не делает, но вы не можете рассчитывать на это. То, что он делает, зависит от компилятора.

new и malloc также могут иметь совершенно разные реализации. Например, delete всегда вызывается в контексте, в котором содержится точная информация о размере структуры данных, которую он удаляет во время компиляции. free не имеет этой роскоши. Возможно, что используемый new распределитель может не хранить байты в начале области памяти, указывающей, сколько байтов он занимает. Это может привести к тому, что free сделает что-то не так, и ваша программа потерпит крах при освобождении чего-либо, выделенного с помощью new.

Лично, если заставить людей делать правильные вещи или исправить код самостоятельно совершенно невозможно, я бы объявил свой глобальный operator new, который вызывал malloc, так что free точно не потерпел бы крах, даже если бы все равно не вызывай деструктора и будь вообще по-настоящему уродливым.

4 голосов
/ 31 октября 2010

Короче говоря, это так же плохо, как неопределенное поведение.

Это тихо говорит само за себя.

C Стандарт ($ 7.20.3.2 / 2) - "Свободный Функция вызывает пространство, указанное на посредством ptr быть освобожденным, то есть предоставлены для дальнейшего распределения. Если ptr - пустой указатель, никаких действий происходит. В противном случае, если аргумент не соответствует указателю ранее возвращаемый calloc, malloc или функция realloc, или если пространство имеет был освобожден с помощью звонка на бесплатную или realloc, поведение не определено. "

4 голосов
/ 31 октября 2010

Вы абсолютно правы, это НЕ правильно.Как вы сами сказали, бесплатно не вызовут деструктора.Даже если у Packet нет явного деструктора, он использует унаследованный.

Использование free для объекта, созданного с помощью new, похоже на уничтожение только того, что может получить мелкая копия.Для глубокого уничтожения нужна функция деструктора.

Кроме того, я не уверен, что объекты, созданные с помощью new (), находятся на той же карте памяти, что и память malloc ().Думаю, они не гарантированы.

2 голосов
/ 31 октября 2010

если кто-то создает объект:

Packet* thePacket = new Packet();

Имеет ли значение, уничтожено ли при удалении thePacket;или бесплатно (Пакет);?

Да, это имеет значение.free (thePacket) будет вызывать неопределенное поведение, но delete thePacket не будет, и мы все знаем, что неопределенное поведение может иметь катастрофические последствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...