0

Can gcc somehow initialize uninitialized pointers to NULL?

At work, we build our software on both gcc 4.1.2 as well as Sun Studio 12. The gcc version, running on Red Hat Enterprise Linux, has been running fine, 5 days a week, for several months.

We just rolled out our Solaris version though, and it crashes on startup, every day.

The stack trace brings us to code like this:

if( _timer == NULL ) {
    _timer = new Timer(bunch, of, parameters);
}
_timer->StartTimer(_timeout);

And we have identified _timer as not having been initialized anywhere. So we believe _timer must be set to garbage data, which fails comparison to NULL, then gets StartTimer'ed without a timer ever being constructed.

The work is actually assigned to my colleague and he's verifying this. But meanwhile, I was curious: Why didn't our Linux (gcc) build crash, ever? I can assure you it's the same code—we use Perforce and strict labeling. I read that compilers do not initialize uninitialized pointers, so I'm confused.

Confirmation that gcc 4.1.2 absolutely cannot auto-initialize an uninitialized pointer, would answer this question. Or, ways it might.

Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145
  • Oh, `NULL` is probably a `#define` or something in my company. It is equal to 0. – Andrew Cheong Apr 11 '17 at 18:22
  • 6
    It's Undefined Behaviour, one symptom of UB is appearing to work. – Richard Critten Apr 11 '17 at 18:25
  • Blind guess but if `__timer` is dereferenced somewhat before (even in a code path not actually taken), the compiler is free to assume that it can never be `NULL`; therefore the initialization code is never executed and not actually compiled. It works with GCC because Jupiter is ascending over the second teapot of the holy cross in the southern islands of the mighty rock. I'd suggest you compile on Sun without any optimizations, just for the lols. – user2722968 Apr 11 '17 at 18:25
  • 1
    Is _timer variable or class member? Is it on stack or in global scope? Static or automatic? – Tomek Apr 11 '17 at 18:27
  • Where's the [mcve]? – R Sahu Apr 11 '17 at 18:40
  • @RichardCritten - Hm, so even if the gcc version never crashed after over 100 startups, and the Solaris version crashes every single startup, undefined behavior can be consistent depending on the platform? (Not being argumentative, genuinely curious.) – Andrew Cheong Apr 11 '17 at 19:11
  • @RSahu - Thank you, but I don't know how you expect me to create a minimal version of enterprise code comprising over half a million LOC, and probably even if I isolated this binary, over 50,000 LOC. Let's be practical. I'm asking a fairly objective question about whether it is possible for a compiler to do something. It can be answered by something like, _"If a compiler **does** do that, then it's violating the C++ standard,"_ or, _"A compiler **can't** do that because then what would happen to code like such and such, in everyday use."_ – Andrew Cheong Apr 11 '17 at 19:16
  • 1
    @AndrewCheong maybe on one platform the OS memory manager always provides 0 initialized memory pages (say for security reasons), or may be the binary ABI is different on the two platform so it is picking up a different location/value. UB does not mean random behaviour, in fact given the deterministic behaviour of computers I would be surprised if it was random on a single platform. – Richard Critten Apr 11 '17 at 19:58
  • @RichardCritten - I see, thank you. – Andrew Cheong Apr 11 '17 at 20:02
  • 1
    @AndrewCheong Whether or not it's possible may hinge on what other code does, for example whether or not it dereferences `_timer`. For example, if you do `_timer->foo()` and `foo` does `if (this == NULL) return;`, the code may not crash on one implementation, but on another, it permits the compiler to assume `_timer` is not NULL. (Technically you've dereferenced `_timer`, but many platforms won't crash even if it's NULL.) So without seeing the code, we really can't say. – David Schwartz Apr 11 '17 at 20:20

0 Answers0