joelkp The behavior of malloc, etc., with size 0 is implementation-defined, it turns out.
Yes. Interesting, also, to compare man-pages:
If the size of the space requested is 0, the behavior is
implementation-defined: either a null pointer shall be returned,
or the behavior shall be as if the size were some non-zero value,
except that the behavior is undefined if the returned pointer is
used to access an object.
As someone once explained to me: implementation-defined means the implementer is free to choose what will be done in certain cases, but, the choice will then have to be documented. undefined means, well, anything can happen, so no documentation is needed. According to POSIX, therefore, at this point your program has gone off the rails:
*s = 'a';
NULL may also be returned by a successful call to malloc() with a
size of zero, or by a successful call to calloc() with nmemb or
size equal to zero.
"... may also be returned ...". Yes, very helpful.
FreeBSD says nothing for the standard
malloc & friends, but, for the FreeBSD-specific functions, passing a
size = 0 to will result in undefined behaviour.
NetBSD 9.1 says:
If size is 0, either NULL or a pointer that can be safely passed
to free(3) is returned.
NetBSD 4.0.1 used to say:
It can be argued that returning a null pointer when asked to
allocate zero bytes is a silly response to a silly question.
but, this was removed in NetBSD-5.0. Somebody please put this bit of whimsy back.
If nmemb or size is equal to 0, a unique pointer to an access
protected, zero sized object is returned. Access via this pointer
will generate a SIGSEGV exception.
which is what you're seeing.
On the whole, I like OpenBSD's version, with NetBSD-4.0.1's coming a close second.