Assertions are an excellent thing, but not to be confused with parameter/return value checking. You use them in situations that you don't believe will occur, not in situations that you expect could occur.
My favourite place to use them is in code blocks that really shouldn't be reached - such as a default
case in switch
-statement over an enum that has a case
for every possible enum value.
It's relatively common that you might extend the enum with new values, but don't update all switch
-statements involving the enum, you'll want to know that as soon as possible. Failing hard and fast is the best you can wish for in such circumstances.
Granted, in those places you usually want something that breaks in production builds as well. But the principle of abort()
ing under such conditions is highly recommended. A good stack trace in the debugger gives you the information to fix your bug faster than guessing around.