Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I pass a null pointer to memcmp?

Tags:

c++

c

memcmp

In particular, is the following well-defined, or does it exhibit undefined behavior?

memcmp(0, 0, 0);

Does this differ between C and C++? Ideally, please provide a quote from the standard(s).

like image 298
avakar Avatar asked May 03 '13 15:05

avakar


People also ask

How do you pass a null pointer?

To pass a null pointer parameter value, specify a value of zero (0) in the external function call. For String and Binary parameters, a value of zero (0) yields a null pointer for the parameter value of the external function.

Can you memcpy null?

Passing a null pointer to memcpy() would produce undefined behavior, even if the number of bytes to copy were 0. The user_data pointer could be invalid in other ways, such as pointing to freed memory. However there is no portable way to verify that the pointer is valid, other than checking for null.

Can you point to a null pointer?

A pointer can't point to null. It can be a null pointer, which means it doesn't point to anything. And a declared object can't be deleted as long as its name is visible; it only ceases to exist at the end of its scope. &value is a valid address at the time the assignment nullPointer = &value; is executed.

Does memset check for null?

AFAIK memset isn't required to check for NULL, so if the malloc fails you'll zero size bytes starting from address 0.


2 Answers

In particular, is the following well-defined, or does it exhibit undefined behavior?

It's undefined. C99 7.21.1/2 says about all the string functions:

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

and the description of memcmp in 7.21.4.1 doesn't explicitly state otherwise.

Does this differ between C and C++?

No, C++ defers to C for its definition of the C library functions, and doesn't have anything special to say about memcmp.

like image 50
Mike Seymour Avatar answered Sep 18 '22 14:09

Mike Seymour


It is amazing that although this appears to be a case of an obvious bug in the standard - which neglects to say that zero-length memcmp is fine (and always returns 0) - mountains of theory was built to explain why this should be labeled "undefined behavior". The above accepted answer is a good example, and so is the later discussion here.

Sadly, after the theory that memcmp(0,0,0) is undefined took hold, Gcc decided to strongly enforce this unfortunate decision, by adding a __nonull attribute to memcmp, causing possibly-wrong optimizations and UBSAN warnings. Only at that point, did this call really become undefined :-(

But if we were to look at it logically, memcmp(0, 0, 0) is well-defined, and should always returns 0 (equality): The functionality of memcmp() is described in Posix as:

The memcmp() function shall compare the first n bytes (each interpreted as unsigned char) of the object pointed to by s1 to the first n bytes of the object pointed to by s2.

When n=0, this means no bytes will be compared. If no bytes are compared, no pointer should ever be dereferenced, and it doesn't matter what this pointer is. That should be obvious, and the fact that the C standard forgot to mention it is nothing more than a bug in the standard.

Interestingly, the Linux memcmp(3) and the FreeBSD memcmp(3) manual pages, disagree with gcc, and claim that this case should be allowed:

The Linux manual page says:

If n is zero, the return value is zero.

While the BSD one says:

Zero-length strings are always identical.

like image 29
Nadav Har'El Avatar answered Sep 21 '22 14:09

Nadav Har'El