
On Thu, Oct 13, 2011 at 12:32 PM, Dave Abrahams <dave@boostpro.com> wrote:
Is it a logic error or a runtime error? IMO exceeding the capacity here is a logic error and should be handled with an assert by default. Isn't it comparable to doing a pop_back() on an empty vector?
Indeed; I object to handling something that is almost certainly going to be a programming error with a defined behavior of throwing an exception (yes, I think std::vector::at is a mistake), for several reasons:
- It limits your ability to detect bugs: once you make the behavior defined, you don't know whether a programming error has been committed anymore.
- It responds by unwinding, which can destroy valuable debugging information
- It does way more than absolutely necessary, which, in a program whose invariants may be broken, may prevent emergency measures from completing successfully.
That said, I am not a security guy, and I understand those people who want to eliminate avoidable, open-ended, undefined behavior whenver possible. Therefore I think that it might make sense to establish a BOOST_SEMISECURE mode, and to encourage library authors are free/encouraged to say something like:
If <some requirement> is not satisfied, the behavior is undefined.
In BOOST_SEMISECURE mode the library will (or may) check <some requirement> using BOOST_ASSERT.
The point being that
a. We can unambiguously mark some usage as incorrect b. Those who don't want it don't have to pay for the check c. The behavior of check failures can be tuned.
This makes me curious. If logic errors should only be caught with an assert in the case of defining a specific macro definition, is there still a case where one should use std::logic_error and family? If not, does that amount to de facto deprecation?