3

Can operator delete throw an exception or signal in some other way of error during memory de-allocation?

In other way is it possible for operator delete to fail and what is it's default behavior in this case?

Also what did ISO standard says about this?

For example in Windows OS - C++ operator new and operator delete are normally implemented via functions HeapAlloc and HeapFree. The later function returns a boolean value which clearly indicates a fail is possible. Imagine how C++ operator delete will be written on it:

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

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

    //return bSuccee ????????????
}
AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • http://www.cplusplus.com/reference/new/operator%20delete%5B%5D/ will help. No throws are ever thrown, guaranteed. After deletion the pointer is invalid. – Evan Carslake Apr 06 '15 at 16:37
  • 1
    That's a little like comparing apples to oranges, to be honest... It looks like your question is *why does C++ not allow `operator delete` to fail with determined behavior, since some operating systems have facilities that allow this?* The answer would then be *because C++ runs on many other operating systems.* – Frédéric Hamidi Apr 06 '15 at 17:13
  • You can't write an operator delete that returns since that is non standard. – NathanOliver Apr 06 '15 at 17:15
  • @Frédéric Hamidi That's way I don't see a reason why overloads of it returning boolean or throwing exceptions doesn't exist. – AnArrayOfFunctions Apr 06 '15 at 17:15
  • @FISOCPP, what would happen on OSes that do not support such a facility? Clearly `delete` returning something or not cannot be implementation-dependent (you would have two different languages then). If `delete` being able to throw or not was implementation-dependent... I don't think any "real" C++ programs would be able to run portably. So, least common denominator it is. – Frédéric Hamidi Apr 06 '15 at 17:20
  • On Windows, HeapFree cannot fail if the arguments are valid and the heap is intact. If you're implementing a runtime, there are two sensible choices for error handling: either ignore the return value (on the grounds that if it does fail, there isn't anything you can do about it) or check the return value and terminate the program immediately if the call fails (on the grounds that something has gone so badly wrong that there is no hope of recovering). I would hazard a guess that the first choice is most common for production runtimes and the second choice is most common for debug runtimes. – Harry Johnston Apr 07 '15 at 04:48

2 Answers2

4

In C++11 18.6 delete is defined as a noexcept function. From section 5.3.5 Delete

If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression.82 If not, the behavior is undefined. [ Note: this means that the syntax of the delete-expression must match the type of the object allocated by new, not the syntax of the new-expression. —end note

emphasis mine

From this we can see using delete in a manner it isn't intended to be used is UB.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • My intention was else. What if the memory can't be deallocated at the moment? What then? Like the input is ok but the function is not capable to achieve the task. – AnArrayOfFunctions Apr 06 '15 at 16:52
  • if the memory can't be de-allocated that to me is an OS issue and not in the purview of C++ – NathanOliver Apr 06 '15 at 16:53
  • @Frédéric Hamidi I said 'can't be deallocated' not 'cannot be allocated'. – AnArrayOfFunctions Apr 06 '15 at 16:54
  • @NathanOliver But why then allocating memory fails isn't an OS issue? – AnArrayOfFunctions Apr 06 '15 at 16:55
  • 1
    @NathanOliver: Example of "cannot be deallocated": the metadata block placed right before the allocated memory has been corrupted by an array overrun. OS is not involved. But in such cases, undefined behavior has already occurred. I'm fairly certain that deallocation failure can only happen following some other form of UB. – Ben Voigt Apr 06 '15 at 16:57
  • That makes sense @BenVoigt. I was thinking in the terms of calling delete, the destructor is called and exits but the memory is never freed by the OS. – NathanOliver Apr 06 '15 at 16:58
  • Maybe it have other reason not to be able to deallocate it - how do you know? For example the return value of 'HeapFree' in Windows is a boolean and that's the equvailent of delete in it - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366701(v=vs.85).aspx. – AnArrayOfFunctions Apr 06 '15 at 16:59
  • Or more closely are the windows resources which can be closed (or deleted) with 'CloseHandle' that returns boolean too. As the most famous OS imposes this behavior - I don't understand why C++ not. – AnArrayOfFunctions Apr 06 '15 at 17:03
  • @FISOCPP: Fame has nothing to do with it. C++ defines a memory model in which legitimately allocated memory can always be deallocated. If the OS is unable to meet that requirement, then the C++ runtime has to provide a conforming implementation in its place. One would hope that the Windows function can only fail if the memory wasn't legitimately allocated, in which case C++ gives undefined behaviour, so your naive implementation would be fine. If there are other circumstances where it might fail, the runtime would have to deal with them in a conforming manner. – Mike Seymour Apr 08 '15 at 01:01
2

Operator delete is noexcept since C++11, so it doesn't throw, see http://en.cppreference.com/w/cpp/memory/new/operator_delete

If operator delete throws, then you can end up throwing in destructor, and all bets are off.

vsoftco
  • 55,410
  • 12
  • 139
  • 252