For one reason or another, I want to hand-roll a zeroing version of malloc()
. To minimize algorithmic complexity, I want to write:
void * my_calloc(size_t size)
{
return memset(malloc(size), 0, size);
}
Is this well-defined when size == 0
? It is fine to call malloc()
with a zero size, but that allows it to return a null pointer. Will the subsequent invocation of memset
be OK, or is this undefined behaviour and I need to add a conditional if (size)
?
I would very much want to avoid redundant conditional checks!
Assume for the moment that malloc()
doesn't fail. In reality there'll be a hand-rolled version of malloc()
there, too, which will terminate on failure.
Something like this:
void * my_malloc(size_t size)
{
void * const p = malloc(size);
if (p || 0 == size) return p;
terminate();
}
Here is the glibc declaration:
extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
The __nonnull
shows that it expects the pointer to be non-null.
Edit Re:
I added this later: Assume that malloc() never fails. The question is only if size can be 0
I see. So you only want things to be secure if the pointer is NULL and the size is 0.
Referring to the POSIX docs
- http://pubs.opengroup.org/onlinepubs/009695399/functions/memset.html
- http://pubs.opengroup.org/onlinepubs/7908799/xsh/memset.html
No, it is not specified that it should be safe to call memset with a NULL pointer (if you called it with zero count or size... that'd be even more 'interesting', but also not specified).
Nothing about it is even mentioned in the 'informative' sections.
Note that the first link mentions
The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of IEEE Std 1003.1-2001 defers to the ISO C standard
Update I can confirm that the ISO C99 standard (n1256.pdf) is equally brief as the POSIX docs and the C++11 spec just refers to the ansi C standard for memset
and friends.
Here's what the C99 standard says about this:
7.1.4 "Use of library functions
If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined.
7.21.1 "String function conventions" (remember that memset()
is in string.h
)
Where an argument declared as size_t n specifies the length of the array for a function, n can have the value zero on a call to that function. Unless explicitly stated otherwise in the description of a particular function in this subclause, pointer arguments on such a call shall still have valid values, as described in 7.1.4.
7.21.6.1 "The memset function"
The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
So strictly speaking, since the standard specifies that s
must point to an object, passing in a null pointer would be UB. Add the check (the cost compared to the malloc()
will be vanishingly small). On the other hand, if you know the malloc()
cannot fail (because you have a custom one that terminates), then obviously you don't need to perofrm the check before calling memset()
.
来源:https://stackoverflow.com/questions/8597034/can-memset-be-called-with-a-null-pointer-if-the-size-is-0