News for hackers. Stuff that matters.
Re:The Dangers of Super Smart Compilers by nkurz on Sunday December 20, 2015 @06:30PM (#10768771)
I thought it would be interesting to see how some different compilers actually behave here. This was my test program:

  nate@haswell:~/tmp$ cat deref.c
  /* gcc -fno-inline -O3 -g -Wall deref.c -o deref */
  /* (or as desired to show particular outcome) */

  #include <stdio.h>
  #include <stdlib.h>

  void deref_and_print(int *ptr) {
    int i = *ptr;  /* undefined behavior if ptr is NULL */
    if (ptr == NULL) printf("NULL\n");
    else printf("%d\n", i);
  }

  int main(int argc, char **argv) {
    int *ptr = NULL;
    if (argc <= 1) {
      printf("Usage: %s [arg]\n", argv[0]);
      printf(" Demonstrates undefined behavior if 'arg'");
      printf(" is not a positive integer\n");
      exit(1);
    }
    int i = atoi(argv[1]);
    if (i > 0) ptr = &i;
    deref_and_print(ptr);
    exit(0);
  }
As you guessed, icc, gcc, and clang all crash with a segfault for 'deref 0' when compiled with -O0. But more interestingly, when compiled with -O1, -O2, or -O3, clang prints "NULL", while icc and gcc continue to crash.
Re:The Dangers of Super Smart Compilers by mikeash on Sunday December 20, 2015 @07:34PM (#10768945)
Nice test. Surprising results for clang. I take it that it doesn't crash for you when it prints NULL? That's the case for me. I'd have thought it would either remove the NULL check and crash, or leave it in but continue to dereference NULL, and thus crash.
Re:The Dangers of Super Smart Compilers by saurik on Sunday December 20, 2015 @09:19PM (#10769227)
The code when it doesn't crash has been reorganized by the compiler so the indirection doesn't even happen until it is preparing the arguments for the printf, which is in an else after the NULL check. If you don't need the value of a computation in one of two sides of an if statement and you know there are no legitimate side effects (I say "legitimate", as crashing does not count) to the calculation, it makes sense to delay the execution of that logic until and unless you actually need it done. I thereby don't find either result surprising here: it is just a demonstration of different optimization decisions and abilities of the two compilers.