What I use asserts for
Somewhat recently a discussion came up about the proper use of asserts over on Ned Batchelder's blog, with a number of people feeling that they were overused or outright misused by being applied to situations that really should have actual error recovery. (One nice phrase used was 'exploding comments'.)
I'll admit it: I use asserts in my code. I use them when I don't think something can happen in an algorithm, but I'm not absolutely sure and if I turn out to be wrong (despite my best testing and thinking about it) the code will explode. This means that my asserts are usually about post-conditions, things like 'however we exit this loop, the buffer must have been emptied', instead of pre-conditions.
(This makes 'exploding comments' not a bad description.)
Checking pre-conditions generally seems like error checking, and I think that asserts are a bad way of checking for errors, whether these are errors in the environment (such as 'out of memory') or errors in how your code is being used. The right way to deal with errors is to raise an exception or return an error status or the like, and thus to make handling them a routine and required part of the interface. (And then you should unit-test these code paths.)
Part of this thinking is due to a long exposure to the Linux kernel
mailing list, where people periodically have to point out that
panic()'ing on an error crashes the user's machine, so perhaps
your code could deal with things like running out of memory a little
bit more gracefully.