The Right Approach to Exceptions

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Feb 23 15:18:27 PST 2012


On Thu, Feb 23, 2012 at 12:07:40PM -0800, Jonathan M Davis wrote:
> On Thursday, February 23, 2012 07:47:55 H. S. Teoh wrote:
[...]
> > The way I understand it, DbC is used for ensuring *program*
> > correctness (ensure that program logic does not get itself into a
> > bad state); defensive programming is for sanitizing *user input*
> > (ensure that no matter what the user does, the program doesn't get
> > into a bad state).
> > 
> > That's why DbC is compiled out in release mode -- the assumption is
> > that you have thoroughly tested your program logic and verified
> > there are no logic problems. Input sanitizing is never compiled out,
> > because you never know what users will do, so you always have to
> > check.
> > 
> > The two do somewhat overlap, of course. For example, failing to
> > sanitize user input may eventually lead to passing invalid arguments
> > to an internal function.
> 
> Exactly. But where things tend to blur is the concept of "user input."
> For instance, if you're using a 3rd party library, should it be
> asserting on the arguments that you pass it?

In my book, a linked library shares equal status with the "main
program", therefore the definition of "user input" still sits at the
internal-to-program and external boundary.


> Unless you compile it in non-release mode, it obviously won't, which
> could be an argument for using exceptions, but regardless of that,
> from the library's perspective, you're a user.

I believe the traditional way is to ship a debug or devel version of the
library which is linked when you compile in non-release mode (e.g.,
libc-dbg), and then in release mode the release mode library is linked
(libc proper). That way DbC will be enforced in non-release mode by the
library, and suppressed in the release mode binary.

If libraries only ship in release mode, then that sorta defeats the
point of DbC, which is to ensure program correctness before release and
not get in the way after. Now the library has to be paranoid and always
sanitize all inputs.


> If it used DbC, it would be putting assertions it in its own code to
> test _your_ code.  And since you're a user, it arguably should use
> exceptions to make sure that the arguments that it gets are correct.

No, the library should ship a development version with all contracts
compiled-in, so that contract violations will be enforced during
development & testing.

Sadly, this isn't often done in practice, which leads to the sad
situation where the program/library boundary has a lot of overhead,
because the library must be paranoid and always sanitize all inputs no
matter what.


[...]
> Arguably, the best thing would be if there was a way for the caller to
> indicate whether it wanted the callee to have DbC enable and possibly
> even indicate whether it wanted the callee to use DbC or defensive
> programming. But there's no way to do that in D, and I'm not sure that
> it could even be done with the C linking model - at least, there's no
> way to it without templatizing everything and giving an argument to
> the template indicating what you want, which obviously isn't a good
> solution (and won't work at all in the case of virtual functions,
> since they can't be templatized).
[...]

No need to templatize anything, just ship two versions of the library,
one with DbC compiled in, one without. Let the user decide which one to
link in.


T

-- 
Never trust an operating system you don't have source for! -- Martin Schulze


More information about the Digitalmars-d mailing list