Archive for April, 2010

NULL can be a valid address

It is only a convention to consider NULL (0) as an invalid pointer. Technically, the operating system or hardware does not really care if a pointer is zero or not, although operating systems may restrict the use of valid null pointers as they may be a security hole.

Consider this program:

#include <stdio.h>
#include <sys/mman.h>

int main ()
{
    int *p = mmap (0, 4096, PROT_READ|PROT_WRITE,
        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    *p = 2554;
    printf ("p=%p; *p=%d\n", p, *p);
    return 0;
}

It attempts to make NULL (0) a valid address and then write to it. On Linux, it runs without error as root, but crashes as a normal user.

Note: Calling mmap with NULL as its first argument usually means the kernel will choose an address. However, if MAP_FIXED is also specified, it instead instructs the kernel to use the very address 0. Only privileged processes are allowed to do so; a non-privileged process only gets EPERM (Permission denied).

This also explains why MAP_FAILED is equal to (void *)-1 instead of NULL.

Tags: , ,

What exactly “-march=native” means

GCC 4.2 introduced “-march=native”. With this option, GCC automatically optimizes for local computer.

I used to think GCC would simply replace it with an appropriate “-march=....” based on results of CPUID, so, for example, it would be equivalent to “-march=core2” on a Core 2 CPU.

Actually GCC does more than I guessed. We can observe what GCC actually replaces it with:

  1. Run

    gcc -march=native -c -o /dev/null -x c -

    in one terminal;

  2. Open another terminal and type

    ps af | grep cc1

    Then we will see how carefully GCC detects our CPU.

I tried this using GCC 4.4.1 on a computer equipped with a Core i3 CPU, and it turns out “-march=native” means

-march=core2 -mcx16 -msahf -mpopcnt -msse4.2 --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=256 -mtune=core2

on this computer. It says:

  • We can use SSE4.2 instructions, CMPXCHG16B, SAHF/LAHF (in 64-bit mode), POPCNT, in addition to all instructions available on a Core 2;
  • The size of L1 and L2 caches are 32KiB and 256KiB, respectively; each L1 cache line is 64 bytes;
  • Use instructions that are most suitable for Core 2 (Sure Core i3 is different from Core 2, but it is too new to have specific optimization support in compilers).

So, the conclusion: always use “-march=native” when compiling codes for local use.

Tags: