С++ может оператор удалить не удается, а если нет, то почему?

Может ли оператор delete генерировать исключение или сигнализировать каким-либо другим образом об ошибке во время освобождения памяти?

По-другому возможен ли сбой operator delete и каково его поведение по умолчанию в этом случае?

И что об этом говорит стандарт ISO?

Например, в ОС Windows - C++ operator new и operator delete обычно реализуются через функции HeapAlloc и HeapFree. Более поздняя функция возвращает логическое значение, которое ясно указывает на возможность сбоя. Представьте, как на нем будет написано C++ operator delete:

void operator delete(void *pMem)
{
    extern HANDLE hHeap;
    extern DWORD dwFlags;

    BOOL bSuccee = HeapFree(hHeap, dwFlags, pMem);

    //return bSuccee ????????????
}

person AnArrayOfFunctions    schedule 06.04.2015    source источник
comment
cplusplus.com/reference/new/operator%20delete%5B%5D поможет. Никакие броски никогда не бросаются, гарантировано. После удаления указатель недействителен.   -  person Evan Carslake    schedule 06.04.2015
comment
Если честно, это немного похоже на сравнение яблок с апельсинами... Похоже, ваш вопрос заключается в том, почему C++ не позволяет operator delete завершать работу с определенным поведением, поскольку в некоторых операционных системах есть средства, позволяющие это делать? Тогда ответ будет таким: потому что C++ работает во многих других операционных системах.   -  person Frédéric Hamidi    schedule 06.04.2015
comment
Вы не можете написать оператор удаления, который возвращает значение, поскольку это нестандартно.   -  person NathanOliver    schedule 06.04.2015
comment
@Frédéric Hamidi Таким образом, я не вижу причины, по которой не существует перегрузок, возвращающих логическое значение или выбрасывающих исключения.   -  person AnArrayOfFunctions    schedule 06.04.2015
comment
@FISOCPP, что произойдет в ОС, которые не поддерживают такое средство? Очевидно, что delete возвращать что-то или нет, не может зависеть от реализации (тогда у вас будет два разных языка). Если бы delete возможность бросать или нет, зависела от реализации... Я не думаю, что какие-либо настоящие программы на C++ могли бы работать переносимо. Итак, наименьший общий знаменатель.   -  person Frédéric Hamidi    schedule 06.04.2015
comment
В Windows HeapFree не может дать сбой, если аргументы допустимы и куча не повреждена. Если вы реализуете среду выполнения, есть два разумных варианта обработки ошибок: либо игнорировать возвращаемое значение (на том основании, что в случае сбоя вы ничего не можете с этим поделать), либо проверить возвращаемое значение и завершить работу. программу немедленно, если звонок не удается (на том основании, что что-то пошло не так, что нет никакой надежды на восстановление). Рискну предположить, что первый вариант наиболее распространен для производственных сред выполнения, а второй вариант — для отладочных сред выполнения.   -  person Harry Johnston    schedule 07.04.2015


Ответы (2)


В С++ 11 18.6 удаление определяется как функция noexcept. Из раздела 5.3.5 Удалить

Если операнд имеет тип класса, операнд преобразуется в тип указателя путем вызова вышеупомянутой функции преобразования, и преобразованный операнд используется вместо исходного операнда в оставшейся части этого раздела. В первом варианте (удалить объект) значение операнда удаления может быть нулевым значением указателя, указателем на объект, не являющийся массивом, созданным предыдущим выражением new, или указателем на подобъект (1.8), представляющий объект. базовый класс такого объекта (раздел 10). Если нет, поведение не определено. Во втором варианте (удаление массива) значение операнда удаления может быть нулевым значением указателя или значением указателя, полученным в результате предыдущего выражения нового массива.82 Если нет, поведение не определено. [Примечание: это означает, что синтаксис выражения-удаления должен соответствовать типу объекта, выделенного новым, а не синтаксису нового-выражения. -конец примечания

выделено мной

Из этого мы можем видеть, что использование удаления не предназначено для использования в UB.

person NathanOliver    schedule 06.04.2015
comment
Мое намерение было другим. Что делать, если память не может быть освобождена в данный момент? Что тогда? Вроде вход в порядке, но функция не способна выполнить задачу. - person AnArrayOfFunctions; 06.04.2015
comment
если память не может быть освобождена, это для меня проблема ОС, а не в компетенции С++ - person NathanOliver; 06.04.2015
comment
@Frédéric Hamidi Я сказал, что «нельзя освободить», а не «нельзя выделить». - person AnArrayOfFunctions; 06.04.2015
comment
@NathanOliver Но почему тогда сбой выделения памяти не является проблемой ОС? - person AnArrayOfFunctions; 06.04.2015
comment
@NathanOliver: пример не может быть освобожден: блок метаданных, размещенный непосредственно перед выделенной памятью, был поврежден из-за переполнения массива. ОС не участвует. Но в таких случаях неопределенное поведение уже имело место. Я совершенно уверен, что сбой освобождения может произойти только после какой-либо другой формы UB. - person Ben Voigt; 06.04.2015
comment
Это имеет смысл @BenVoigt. Я думал с точки зрения вызова удаления, деструктор вызывается и завершается, но память никогда не освобождается ОС. - person NathanOliver; 06.04.2015
comment
Может быть, у него есть другая причина, по которой он не может освободить его - откуда вы знаете? Например, возвращаемое значение «HeapFree» в Windows является логическим, и это эквивалентно удалению в нем — msdn.microsoft.com/en-us/library/windows/desktop/. - person AnArrayOfFunctions; 06.04.2015
comment
Или, точнее, ресурсы Windows, которые можно закрыть (или удалить) с помощью «CloseHandle», который также возвращает логическое значение. Поскольку самая известная ОС навязывает такое поведение - я не понимаю, почему С++ нет. - person AnArrayOfFunctions; 06.04.2015
comment
@FISOCPP: слава тут ни при чем. C++ определяет модель памяти, в которой законно выделенная память всегда может быть освобождена. Если ОС не может удовлетворить это требование, тогда среда выполнения C++ должна предоставить соответствующую реализацию вместо себя. Можно было бы надеяться, что функция Windows может дать сбой только в том случае, если память не была выделена законным образом, и в этом случае C++ дает неопределенное поведение, поэтому ваша наивная реализация будет в порядке. Если есть другие обстоятельства, при которых может произойти сбой, среда выполнения должна будет справиться с ними соответствующим образом. - person Mike Seymour; 08.04.2015

Оператор delete является noexcept, начиная с C++11, поэтому он не выбрасывает, см. http://en.cppreference.com/w/cpp/memory/new/operator_delete

Если оператор delete выбросит, то вы можете в конечном итоге добавить деструктор, и все ставки сняты.

person vsoftco    schedule 06.04.2015