I
ImpalerCore
Maybe.
Would you be more willing to accept it if instead of a defensive
programming style, it had a contract programming style? You could
consider the version that silently crashes a contract programming
style, except that the terms of the contract are implicit, discovered
either through the documentation or spending time in the debugger.
\code snippet
#define C_REQUIRE( expr ) \
do \
{ \
if ( !(expr) ) { \
gc_contract_violation( "Precondition failed: " #expr, \
__FILE__, __LINE__ ); \
} \
} while(0)
char* trim( char* s )
{
C_REQUIRE( s != NULL );
... rest of trim ...
return s;
}
\endcode
where C_REQUIRE would basically do what assert does, except with the
added connotation that it's a precondition of the function, rather
than a generic assertion.
No. Here's the thing:
If I were DESIGNING the library, I'd insist on it being robust in that
way, probably. (There's a case to be made, in some environments, for
not doing that -- if things get passed around enough, you're testing
the same pointer for null/not-null dozens of times.)
But since it ISN'T that way, and it's a standard part of the language,
I expect users to know that.
The problem is that a NULL pointer argument can represent valid or
invalid semantics. If the client provides a NULL argument where it is
invalid semantics (like passing a NULL pointer to the printf format
string), it's a software defect and should in an ideal world be
corrected rather than let slide. These viewpoints about function
design seem to be a tradeoff between robustness and correctness.
I ask myself, is the NULL pointer viewed as a valid semantic
representation of a string object? If I looked at it from the point
of designing strlen, I think there _is_ a semantic difference between
strlen( NULL ) and say strlen( "" ). The expression 'strlen( NULL )'
doesn't make any sense because in my mind, NULL isn't a representation
of any valid string buffer, and it's not considered an alternate form
of strlen( "" ). Why should clients be given a false impression that
a NULL pointer is a valid string representation in some string
functions (like trim) and not in others (like strlen, where it results
in a crash)? It gives mixed signals of what a NULL char* pointer
represents.
On the other side, one example that can define a NULL pointer as
semantically valid is a linked list, where the NULL pointer is
commonly used to indicate an empty list.
I think it sometimes does.
Mine is that I basically always do it in my code, and never assume anyone
else does it. Except free() because I'm emotionally attached to the
sanity of free(malloc(1));
My string functions currently do check for null arguments and skip any
processing in their current form, much like your version of trim, but
I'm weighing whether to convert the behavior to use an explicit
precondition like that shown in C_REQUIRE above, to keep the same kind
of no-nonsense pressure the standard library provides to force
developers to use string functions the right way, rather than giving
them the freedom to do it the wrong way.