Является ли вызов оператору "удалять" синхронно?

Мне было интересно, является ли вызов оператору delete синхронным или нет. Другими словами, если я это сделаю:

delete p;

Гарантирует ли стандарт С++, что только после завершения этого вызова память освобождается? Или это асинхронный вызов и просто планирует задачу для ОС освобождать эту память, как только она решит, что это лучшее время для этого?

Если первый случай является допустимым, значит ли это, что мы должны реализовать собственный механизм асинхронного удаления отходов? Я спрашиваю, потому что я бы сказал, что большую часть времени нам (программистам) все равно, когда память освобождается точно, и поэтому мы не хотим, чтобы наш код зависал и дождался этого (скорее всего, дорогого?) системный вызов для завершения, а скорее запланировать задачу для удаления и немедленно продолжить выполнение. Предоставляет ли С++ какой-либо стандартный объект (возможно, через стандартную библиотеку?) Для этого, не изобретая колесо?

Ответы

Ответ 1

delete является синхронным. Теперь это не означает, что базовая память фактически освобождается в то время операционной системой, но с точки зрения системы С++ она ведет себя так, как будто.

Я спрашиваю, потому что я бы сказал, что большую часть времени нам (программистам) все равно, когда память освобождается точно

Но delete is not в основном о памяти, а также о вызове деструктора детерминированным способом - его универсальном ресурсосберегающем механизме, не ограниченном памятью. И здесь важно иметь синхронность, иначе один из основных аспектов С++ - RAII - не работал.

Ответ 2

Ничего не гарантирует, что delete p; освободит память обратно к ОС - когда-либо. Фактически, в довольно многих (большинство?) Реализациях он ничего не сделает.

Точно, сколько будет происходить, когда вы вызываете delete, меняется, хотя в некоторых случаях это почти мгновенно (просто связывает блок со списком свободных блоков памяти). В других он скорее работает: уничтожает объекты и, возможно, ищет текущий свободный список для смежных блоков, которые могут быть объединены с освобождаемым.

Ответ 3

Насколько вам известно, все ведет себя точно так, как вы ожидаете, и нет скрытых ловушек или gotchas. Вы всегда можете сказать T * p = new T; delete p; и это правильно, независимо от того, в каком контексте это происходит.

Учитывая, что операционная система обычно должна распределять память для всех видов процессов и потоков одновременно, вы можете предположить, что эта проблема уже решена правильно.

Более формально, 18.6.1.4/1 ( "Data Races" ) говорит:

Для определения существования расчётов данных версии библиотеки operator new, версии замены пользователя global operator new и стандартные библиотечные функции C calloc и malloc должны вести себя так, как если бы они обращались к изменено только хранилище, на которое ссылается возвращаемое значение. Варианты библиотеки operator delete, версии замены пользователя operator delete, а стандартная библиотечная функция C free должна вести себя так, как если бы они обращались к ним и модифицировали только хранилище, на которое ссылается их первый аргумент.

Относительно "блокировки": все сводится к тому, что делает функция распределения библиотеки C. Ничего не указано за пределами "эта функция возвращает указатель на некоторую память". Это до платформы, как она обеспечивает выделение памяти.

Ответ 4

Бесплатный вызов в C/С++ уже очень быстрый, несмотря ни на что. Нет причин, по которым вы могли бы отложить удаление в течение более подходящего времени в этом отношении. Любая бухгалтерская книга, которую вы должны были бы сделать для этой цели, более чем компенсировала бы фактическую продолжительность бесплатного звонка.

Если ваш деструктор работает больше, чем закрытие сокетов соединений с БД, вы можете выполнить этот тип работы позднее, но это должен быть более исключительный случай.