4

I have a large code that we were using for a long time in our team. But its several weeks that there is a problem with it when it is compiled on my machine. The code is cross compiled for an Intel Atom CPU and ran on an specific machine.

When it is compiled on my computer, unlike anybody else's, it causes a segmentation fault. The segmentation faults is from inside an if block that should not be executed:

Settings *s = &Global::getSettings();
std::cout << "Pointer value before if : " << s << std::endl;
if(s != 0)
{
  std::cout << "Pointer value after if : " << &Global::getSettings() << std::endl;
  .
  .
  .
}

Global::getSettings() is as follows:

.
.
.

private:
  static __thread Settings* theSettings;

public:
  static Settings& getSettings() {return *theSettings;}

.
.
.

__thread Settings* Global::theSettings = 0;

In my test the value of Global::theSettings is not changed and is equal to zero. Output of the upper code snippet is this:

Pointer value before if : 0
Pointer value after if : 0

Question: How can an if be executed with condition equal to zero?!

P.S.: I am using clang++ to compile the code on a Debian machine.

Sheric
  • 416
  • 2
  • 16
  • 2
    My guess is that the compiler saw the dereference in `Global::getSettings()`, inferred that `Global::theSettings` can't be null (or alternatively, saw that `s` is being initialized with `&something` and inferred that it cannot be null), and optimized the null check away. – T.C. Dec 27 '14 at 18:08
  • Is this just an impression, or is your code multithreaded? – Christophe Dec 27 '14 at 18:10
  • It is a multithreaded code but the static variables are defined thread-wide. – Sheric Dec 27 '14 at 18:12
  • Oh, and the error occurs before any thread is started. – Sheric Dec 27 '14 at 18:12
  • Replacing -O3 with -O0 fixes the problem, probably @T.C guess is right. – Sheric Dec 27 '14 at 18:14
  • 1
    [Reproduced on Clang 3.5 with optimizations enabled](http://melpon.org/wandbox/permlink/QedpEC77NXz0NzXc). You may need to reconsider your interface to avoid the UB. – T.C. Dec 27 '14 at 18:16

1 Answers1

9

It is undefined behaviour to store a null pointer in a reference.

So once it is in the reference, the compiler is free to assume the address is non null, and optimize out your null check.

The "success" of other compilers was just one possible symptom of your undefined behaviour.

Do not store or create references to non-objects.

T.C.
  • 133,968
  • 17
  • 288
  • 421
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524