News for hackers. Stuff that matters.
Re:Initialization in C++ is Seriously Bonkers by MaxBarraclough on Saturday January 05, 2019 @06:21PM (#18835022)
> The reason that stack variables are UNinitialized is (contra the article which thinks it's because the programmer didn't put an initializer in the source code) that memory is on the stack, which is allocated internal to your program and in practice was used previously by some other call for some other purpose.

It is because the programmer didn't put an initializer into the source code. That's how the language is defined. What you are discussing is the underlying reason the language is defined that way. You are speaking past the author, not pointing out a mistake.

The blog post does contain a genuine error relating to this point, though: Any C programmer worth anything knows that this initializes i to an indeterminate value. This is wrong. Reading the variable does not simply give you an indeterminate value, it gives undefined behaviour (something the article never mentions, surprisingly).

> that stack variables are uninitialized by default is actually an intentional feature, not a bug, as it correctly expresses the behavior of the runtime environment

But it doesn't. Reading an uninitialized local variable gives undefined behaviour, which might not correspond to the behaviour of using any particular garbage value.

Anyway, the language is defined that way simply for performance reasons. The risk of undefined behaviour is a considerable downside but was deemed acceptable.

> But it's got nothing to do with the syntax of the language.

We're talking about the semantics of C. If C were defined such that static integer variables be initialized with 1 rather than 0, that's what would happen, no?

Re:Initialization in C++ is Seriously Bonkers by codeflo on Saturday January 05, 2019 @06:37PM (#18835135)
You're not wrong, but I think this is a case where knowing the reason for the rules is easier than remembering the actual rules. This is just from personal experience, but for me, remembering what is and isn't initialized in C++ seemed completely arbitrary and insane until I learned more about linking and process startup. YMMV of course.
Re:Initialization in C++ is Seriously Bonkers by MaxBarraclough on Saturday January 05, 2019 @07:20PM (#18835370)
I agree there's a lot of value in understanding hardware/OSs/etc, but it's no substitute for having a solid understanding of C in general. C has much to say on undefined behaviour, and there are no shortcuts - you just have to have a good grasp of the language's dark corners.

(Aside: I believe ++i++; is no longer UB in the latest version of the language, but used to be.)

On the particular topic of initialization in C/C++, I go with the rule of thumb of be as explicit as possible.

Beyond that, I'm not afraid to assign a marker value to a local only to overwrite it soon afterwards. I save myself endless trouble in case my code is buggy, and if it's not, the compiler is likely to elide the first assignment entirely.

Re:Initialization in C++ is Seriously Bonkers by adrianN on Sunday January 06, 2019 @03:10AM (#18837226)
But if you remember the underlying reason you might think that using uninitialized variables gives just gives you an arbitrary value. That's not true, it's UB. The compiler can do whatever it wants if it can prove that you read an uninitialized variable.
Re:Initialization in C++ is Seriously Bonkers by zawerf on Sunday January 06, 2019 @03:25AM (#18837275)
Do compilers really try to prove UB so they can use it as an excuse to silently murder kittens? That sounds so counterproductive. If it can prove UB, it should just pop an error and stop.
Re:Initialization in C++ is Seriously Bonkers by codeflo on Sunday January 06, 2019 @04:00AM (#18837372)
What's actually happening is a bit more subtle: The compiler is allowed to assume that the programmer in fact made no mistake and there's a reason why the UB is never actually triggered at runtime. Reasoning backwards from that can open up large optimization opportunities elsewhere, like not loading a value from memory twice, or not actually checking a condition. A good article about this that was recently discussed on HN: https://news.ycombinator.com/item?id=18575383
Re:Initialization in C++ is Seriously Bonkers by palunon on Sunday January 06, 2019 @05:34AM (#18837656)
What they do is not try to prove UB, but use it as a precondition for the proof that their optimizations don't change the program behavior - ie. they can assume that anything resulting in UB won't happen.
Re:Initialization in C++ is Seriously Bonkers by saagarjha on Sunday January 06, 2019 @05:07AM (#18837559)
> Do compilers really try to prove UB so they can use it as an excuse to silently murder kittens?

Clang in particular is quite aggressive about this, and is prone to producing surprising results. GCC has started doing this too, but it is much more conservative,

Re:Initialization in C++ is Seriously Bonkers by MikeLui on Saturday January 05, 2019 @07:13PM (#18835336)
In the next sentence I say:

> variables must always be initialized before they’re used.

Also I believe I’m quoting close to the standard there about indeterminate value.

I stayed away from using the term “undefined behavior” because I’ve had a lot of problems in the past with students believing undefined behavior means “but it works if they ran a test with a particular compiler version and flags and didn’t see any problems”. No matter how I try to equivocate undefined behavior with invalid code, it has trouble sticking. This is a <edit>understandable</edit> perspective built from starting at interpreted languages that immediately notify of any runtime errors and otherwise don’t have undefined behavior.

Re:Initialization in C++ is Seriously Bonkers by MaxBarraclough on Saturday January 05, 2019 @07:38PM (#18835465)
Your first points are well taken. From a quick googling you're right about the way the spec phrases it. It is, of course, terribly precise about under what circumstances UB occurs - https://stackoverflow.com/a/23429477/

> I stayed away from using the term “undefined behavior” because I’ve had a lot of problems in the past with students believing undefined behavior means “but it works [...]

Seems to me that developing a due terror of UB is vital to having a basic understanding of C as a programming language * , and beyond that, it's vital to appreciating what C is.

As well as being a considerable practical headache (it's not a compiler bug, it's UB going haywire), it's one of the major differences between C and, say, Java (alongside the way C types are not portable, etc). I'd say it deserves some emphasis as a basic principle.

* I suspect some theorists would contend that, strictly speaking, C programs aren't programs, and C isn't a programming language. Programs are, theoretically, meant to unambiguously map inputs to outputs. C is not unambiguous. But, needless to say, I digress.

Re:Initialization in C++ is Seriously Bonkers by saagarjha on Sunday January 06, 2019 @05:09AM (#18837566)
> No matter how I try to equivocate undefined behavior with invalid code, it has trouble sticking.

Try telling students to add -fsanitize=undefined to their compilation flags. That might help make it clear that their code is buggy.

Re:Initialization in C++ is Seriously Bonkers by perl4ever on Saturday January 05, 2019 @10:59PM (#18836485)
"Any C programmer worth anything knows that this initializes i to an indeterminate value. This is wrong. Reading the variable does not simply give you an indeterminate value, it gives undefined behaviour"

Undefined behavior in the technical sense is not acceptable in a language at all, let alone a feature. If you take the idea of undefined behavior seriously, then it is valid to blow up the world in response to an error and the compiler cannot protect you. Nobody would use C or C++ if they actually accepted the meaning of undefined behavior, so to program in these languages requires embracing doublethink.

Re:Initialization in C++ is Seriously Bonkers by MaxBarraclough on Sunday January 06, 2019 @05:50AM (#18837691)
First up, I think I was technically mistaken in saying the blog was technically mistaken. It seems the language spec defines the UB in terms of read-before-assignment, but they do use the term 'indeterminate value' as well. So the blog post can be seen as incomplete, rather than mistaken.

> Undefined behavior in the technical sense is not acceptable in a language at all

The C committee disagrees, and they have their reasons. They're aiming to maximise performance and support for various weird and wonderful platforms.

C's philosophy is not like that of Java where, say, an int is defined to be 32 bit and your machine just has to make it happen, even if it's a peculiar 48 bit machine or something.

> If you take the idea of undefined behavior seriously, then it is valid to blow up the world in response to an error and the compiler cannot protect you

Well sure. UB means you screwed up. C isn't a hand-holding language. Explode the whole process. Perfectly valid. Not without precedent in the C++ spec, incidentally; C++ is defined to explode your process if you screw up in a certain way with exceptions https://stackoverflow.com/a/43675980/

Your program can't literally blow up the world, of course, but that's beyond the scope of the language. If UB could result in nuclear apocalypse, that would mean a compiler bug could generate a binary that did the same thing, regardless of source language.

> Nobody would use C or C++ if they actually accepted the meaning of undefined behavior, so to program in these languages requires embracing doublethink.

Plenty of C/C++ programmers have a very sloppy attitude to undefined behaviour, and sometimes they get bitten by it. Aggressive optimising compilers like gcc, really do depend on you taking responsibility for writing code with defined behaviour. Break that contract, and you can see nightmare intermittent bugs that only appear when using certain compiler flags. See: http://blog.llvm.org/2011/05/what-every-c-programmer-should-...

Of course, this is all made worse by that it's impossible for static analysis to detect all instances of UB. If you want a language that doesn't take this attitude, you might try Ada. It's a pity more people don't.

Re:Initialization in C++ is Seriously Bonkers by Retra on Sunday January 06, 2019 @01:35AM (#18836937)
>If you take the idea of undefined behavior seriously, then it is valid to blow up the world in response to an error and the compiler cannot protect you

That's not its job. The compiler cannot protect you from everything. (You shouldn't be using a computer that has the ability to blow up the world.) The compiler merely translates code from language A into language B. If you pass it some code in some third language which could parse as mal-formed A code, then how is to detect that?

If I write a language with the same syntax as C but entirely different semantics, and I pass it to a C compiler, what do you think should happen? Undefined behavior is what happens.

Re:Initialization in C++ is Seriously Bonkers by nindalf on Sunday January 06, 2019 @02:01AM (#18837012)
> That's not its job. The compiler cannot protect you from everything.

The compiler can protect us from many things, such as uninitialised variables. It’s just that we choose to define the semantics of the C compiler such that it doesn’t.

Also I don’t think GP meant literally, physically destroy the world. It was a metaphor for catastrophic consequences of program misbehaviour. They meant that literally anything could happen, having dire consequences for reliability and security.

Re:Initialization in C++ is Seriously Bonkers by perl4ever on Sunday January 06, 2019 @01:49PM (#18839836)
Right here is what I mean by doublethink. How can "literally anything" not include "literally physically destroy[ing] the world"? Of course, I was also using it as shorthand for any catastrophic consequence that is unacceptable.

It's the equivocation between inconsistent ideas that frustrates me. Of course, practically speaking you assume really bad things don't follow from undefined behavior. But then why the constant refrain about how we shouldn't rely on what actually happens?

I think I understand where the motivation for declaring undefined behavior comes from - people who set standards don't want responsibility for situations they don't completely control. But this disclaiming of responsibility puts the users of the standards in an impossible situation as a result.

I'm coming from a perspective of someone who programmed in C as my second language after BASIC, back in the 80s, before modern standards and before I knew anything about language standards. The philosophy and attitude of people who talk about standards and undefined behavior is something I first encountered on Usenet in the 90s, but I still am disturbed by it and haven't been "educated" to accept it.

Re:Initialization in C++ is Seriously Bonkers by MaxBarraclough on Sunday January 06, 2019 @05:59AM (#18837709)
> If you pass it some code in some third language which could parse as mal-formed A code, then how is to detect that?

This 'other language' approach doesn't strike me as a good way of thinking about it. It misses the point that C is pretty unique in its broad use of undefined behaviour. Unlike Java, where everything has an unambiguous definition. (Well, ignoring plenty of platform-specific variation points in the standard library, such as file-path syntax.)