einpoklum
einpoklum

Reputation: 131666

How can I test my code's behavior when receiving a null-but-not-0, and 0-but-not-null pointer?

I want to adapt a piece of code to be able to run on systems where the null pointer is not 0 in its physical representation. So far in life I've totally ignored the distinction between nullness and 0 - and still today, I don't work on any system which has this distinction in practice - but still.

So, I went and read the C FAQ about nulls again, and particularly 5.19, regarding how to get an "actual zero" pointer. Well, I want to do this in a unit test I'm writing, but - I am worried some of those "tricks" will actually be optimized away by a reasonable compiler.

For example, using memset() and `memcmp(): Both GCC and Clang see right through that, so that this:

#include <stdio.h>
#include <string.h>

int foo(void* p)
{
    void* ref;
    memset(&ref, 0, sizeof(ref));
    return (memcmp(&p, &ref, sizeof(p)) == 0 ) ? 123: 456000;
}

int bar(void* p)
{
    memset(&p,  0, sizeof(p));
    return (p == 0) ? 123: 456000;
}

becomes, say:

foo:                                    # @foo
        test    rdi, rdi
        mov     ecx, 123
        mov     eax, 456000
        cmove   eax, ecx
        ret
bar:                                    # @bar
        mov     eax, 123
        ret

So, other than compiling without optimizations, how can I reliably "force a zeroing" of a pointer?

Note: Thanks goes to @Lundin for pointing out that if I use memset() I also probably want to use memcmp()).

Upvotes: 2

Views: 169

Answers (1)

Lundin
Lundin

Reputation: 214060

memset is the correct solution. And since you compile with compilers that uses zero as null pointer implementation, it might be quite hard to block optimizations from happening.

You have a bug though.

  • A check of a pointer such as if(p) checks if that pointer is a null pointer.
  • A comparison p == 0, p == (void*)0 or p == NULL checks if that pointer is a null pointer.

So p == 0 does not check if the internal representation is zero. You'd have to use something like:

void* ref;
memset(&ref, 0, sizeof ref);

if(memcmp(&p, &ref, sizeof p)==0)

Which again probably won't result in anything revolutionary on a system using zero for null pointer representation.

Upvotes: 2

Related Questions