Должно ли быть выдано предупреждение или, возможно, даже ошибка подтверждения, если delete используется для освобождения памяти, полученной с помощью malloc ()? - PullRequest
14 голосов
/ 03 апреля 2010

В C ++ использование delete для освобождения памяти, полученной с помощью malloc(), не обязательно приводит к взрыву программы.

Следует ли выдавать предупреждение или, возможно, даже ошибку подтверждения, если delete используется для освобождения памяти, полученной с использованием malloc()?

Почему у Страуструпа не было этой функции на C ++?

Ответы [ 9 ]

22 голосов
/ 03 апреля 2010

В C ++ использование delete для освобождения памяти, полученной с помощью malloc (), не обязательно приводит к взрыву программы.

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

Считаете ли вы, ребята, предупреждение или, возможно, даже ошибка подтверждения, если удаление используется для освобождения памяти, полученной с помощью malloc () ??

Нет. Это сложно, если не невозможно, проверить во время компиляции. Проверка во время выполнения обходится дорого, а в C ++ вы не получаете того, за что не платите.

Это может быть полезным вариантом для включения во время отладки, но на самом деле правильный ответ - просто не смешивать и не сопоставлять их. У меня не было проблем с этим.

9 голосов
/ 03 апреля 2010

delete обладает специальным свойством, которого нет у free(): он вызывает деструкторы, которые, в свою очередь, могут вызывать больше удалений, поскольку этот объект мог выделить другие объекты в куче.

Тем не менее, new также вызывает конструктор объекта, а malloc() - нет. Не смешивайте эти вещи, если вы абсолютно не уверены, что знаете, что делаете (и если бы вы это сделали, вы бы не смешали эти вещи в любом случае).

2 голосов
/ 03 апреля 2010

В C ++ использование delete для освобождения памяти, полученной с помощью malloc (), не обязательно приводит к взрыву программы.

Ты никогда не должен этого делать. Хотя некоторый компилятор выделяет память для новых, используя malloc, free () не вызывает деструкторы. Так что, если вы смешаете «новое» со «бесплатным», вы получите утечки памяти, и вам будет трудно справляться с проблемами. Просто забудь это. Это не стоит усилий.

Как вы думаете, ребята, предупреждение или, возможно, даже ошибка подтверждения должны быть выданы, если удаление используется для освобождения памяти, полученной с помощью malloc () ??

Насколько я знаю , при попытке MSVC удалить () память, выделенная с помощью malloc, выдает ошибку отладки (что-то вроде «pCrtBlock is not valid», хотя точное сообщение не помню). То есть - если проект был собран с отладочными библиотеками crt. Происходит потому, что debug new () выделяет дополнительную память для каждого выделенного блока, и этот блок не существует в памяти, выделенной с помощью malloc.

Почему вы думаете, что у Страуструпа не было этой функции на C ++?

По моему мнению, программисту должно быть позволено выстрелить себе в ногу из ракетницы, если он действительно хочет это сделать. delete () даже не должен быть совместимым с malloc, поэтому добавление защиты от полной глупости не стоит усилий для создания функции.

1 голос
/ 14 июля 2010

Лично неопределенное поведение схем смешивания и сопоставления распределения памяти делает нежелательным даже смешивать их в одной программе / библиотеке.

Существуют некоторые инструменты статического анализа, которые могут идентифицировать этот вид дисбаланса распределения / освобождения памяти и генерировать для вас предупреждения. Однако статический анализ никогда не бывает на 100% точным или надежным, так как всегда будут ограничения в способности инструментов отслеживать переменные и места в памяти в программе.

Полное раскрытие: я работаю в Red Lizard Software , пишу инструмент статического анализа goanna для C / C ++, и он способен обнаруживать такое несоответствие в некоторых, а не во всех случаях.

1 голос
/ 03 апреля 2010

Предупреждение было бы неплохо, но, вероятно, этого не произойдет, потому что C ++ изначально был построен на C, поэтому ошибка времени выполнения не может быть сгенерирована, потому что malloc является допустимым C.

Это по-прежнему крайне плохая практика, даже если ваша программа не падает ...

0 голосов
/ 13 апреля 2011

Нет. Не может быть сделано Я могу (законно и в соответствии со спецификацией) перегрузить new () и delete (), чтобы использовать malloc и free (как я делал раньше), и в этот момент, ну, на самом деле, не совсем понятно, каково ваше утверждение сделал бы со мной.

0 голосов
/ 14 июля 2010

Нет. Предупреждение не может быть выдано, потому что невозможно определить, был ли указателю назначен фрагмент памяти из malloc, new или он просто указывает куда-то во время компиляции.

Утверждение - это хорошая функция, так же как и проверка границ массива, проверка указателей NULL и т. Д., Но C ++ - это неуправляемый язык программирования, предполагающий, что вы знаете, что делаете.

0 голосов
/ 03 апреля 2010

Нет.

При программировании компилятора предупреждения - это вторая сложная задача для разработки.

Поэтому у вас обычно есть предупреждения против важных элементов, как, например, "что-то, что действительно может случиться спрофессионал ", а не в огромном разнообразии совершенно глупого неправильного использования API.Кроме того, malloc и новые выделенные указатели могут быть невозможно различить во время компиляции.

0 голосов
/ 03 апреля 2010

Я не знаю, почему компиляторы этого не делают, это кажется полезным.

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

Во время выполнения среда выполнения c ++ уже добавляет много дополнительной информации о некоторых компиляторах для определения переполнения буфера и т. Д. В сборках отладки, поэтому я не понимаю, почему он не может добавить флаг в блок памяти, чтобы сказать как это было распределено и как-то сообщать об ошибке, если она не работает.

Полагаю, реальный ответ в том, что на самом деле он вообще поймает много ошибок. Кажется, здесь каждый день возникает очень много вопросов с новым вопросом о смешивании new и malloc, и все же за 10 лет программирования я никогда не видел программы, которая бы это делала. Программы на C используют malloc, программы на c ++ используют new, и я почти никогда не видел их смешанными. Если вы используете C ++, вы просто используете новый для всего. Я думаю, что существует устаревший код, который изначально был C и был повторно использован в C ++, но я сомневаюсь, что этого достаточно, чтобы это стало большой проблемой в реальной жизни.

Кто-нибудь когда-нибудь имел проблемы с этим в реальной программе?

...