Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no cleanup if a contract precondition fails?

C++26 will introduce function contract specifiers, which are contract assertions associated with a function to express and check that function's pre- and post- conditions.

If enforced, contract violation will lead to the program being terminated as well as the outputting of some diagnostic information.

I understand that:

  1. If a precondition or postcondition is not met, continuing to execute the function is meaningless, hence why it is currently common to exit the function upon detection, by throwing an exception or otherwise
  2. Although some languages use exceptions to signal precondition violations, C++ seems to be moving away from that so that exceptions will only be used to provide a way to recover from errors due to external factors (such as a file that can't be opened due to missing permissions)

It is therefore not surprising that contract violation will lead to program termination, but it will do so through std::terminate() or std::abort(), neither of which allows to unwind the stack and call destructors, i.e. to perform cleanup through RAII.

That seems strange to me, as it seems to me to always be preferable to perform cleanup if possible (for example some of my code tells hardware components to send messages periodically over a bus, I tell them to stop on program exit through a destructor, and I'd still like to do that if I detect a violation).

Is there any reason I should not use instead an assertion function that would unwind the stack and call destructors when it detects a violation? (and for that matter, is there actually a way to implement such a function? I can't find a way to unwind the stack and call destructors besides throwing an exception)

like image 236
Eternal Avatar asked Aug 31 '25 04:08

Eternal


1 Answers

If enforced, contract violation will lead to the program being terminated as well as the outputting of some diagnostic information.

Not necessarily. The enforce semantic only ensures that the implementation will attempt to terminate the program if the contract violation handler returns normally. This is called "contract-termination". See [basic.contract.eval] paragraphs 9 and 13. The contract violation handler is permitted to throw an exception, which can then be caught by the function that called the function whose precondition was violated (or some other function further in the call stack). See paragraph 17.

There is, however, also a quick-enforce contract semantic that causes immediate contract-termination without calling the contract violation handler. In that case it's usually not possible to recover.

like image 79
Brian Bi Avatar answered Sep 02 '25 16:09

Brian Bi