News for hackers. Stuff that matters.
Re:Initialization in C++ is Seriously Bonkers by ajross on Saturday January 05, 2019 @01:35PM (#18833314)
> [Why is a global variable zero?] Because i has static storage duration, it’s initialized to unsigned zero. Why, you ask? Because the standard says so.

No, it's because i lives in an area allocated at the OS level, and OS has to have initialized that memory with something (otherwise you'd have a security bug). The .bss segment has been zeroed, for obvious reasons, since the advent of modern linkage.

The explanation is backwards. 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.

The fact 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. Now, it may not be a good feature, and modern language designs have omitted it (by, let's remember, relying on much better modern compilers to elide all the extra code that would otherwise have been needed to zero out a stack frame!).

But it's got nothing to do with the syntax of the language. You can rely on .bss being zero in assembly, and similarly be surprised that stack memory is going to have junk in it.

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.)

Re:Initialization in C++ is Seriously Bonkers by ori_b on Saturday January 05, 2019 @02:01PM (#18833512)
> No, it's because i lives in an area allocated at the OS level

What OS? I don't have one. I have to link in init code to zero sections of ram before my embedded code runs.

Sure, it got into the standard because some popular OSes like Unix zero initialized pages, but it's not a universal truth. The reason it's guaranteed in C is because of the spec.

Re:Initialization in C++ is Seriously Bonkers by pooppaint on Saturday January 05, 2019 @06:06PM (#18834925)
Dear lord sounds like you got lost from comp.lang.c. How did it get into the spec? Because Unix did it that way. Just like gets made it into the spec. It’s not like that was some willful good design. The history of C and it’s standarization is inextricably ties to the history of Unix.
Re:Initialization in C++ is Seriously Bonkers by valarauca1 on Saturday January 05, 2019 @02:53PM (#18833812)
Not necessarily true.

C89 only requires that static values be initialized.

A modern C standard (section: 6.7.8(10)) requires static values be initialized, but what the value is initialized too be _technically_ indeterminate.

There is the guide line given that integers must be zero, and pointers be NULL. But if a static storage class isn't consisting of purely integers, pointers, or (fixed sized) structures, arrays, and unions who's elements can recursively reduced to integers or pointers. Then the standard says the initialized value is indeterminate.

While relatively straightforward, there is a few gotcha's.

Re:Initialization in C++ is Seriously Bonkers by tom_ on Saturday January 05, 2019 @04:15PM (#18834316)
The C11 rules for static values are pretty explicit:

``` If an object that has static or thread storage duration is not initialized explicitly, then:

- if it has pointer type, it is initialized to a null pointer;

- if it has arithmetic type, it is initialized to (positive or unsigned) zero;

- if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

- if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits; '''

I think that covers every possible value you can create, and it seems pretty non-indeterminate by my reading.

Re:Initialization in C++ is Seriously Bonkers by lasagnaphil on Saturday January 05, 2019 @01:47PM (#18833414)
I always think C/C++ is not a good first language to teach, because you need to understand some general concepts about computer systems before diving in. Probably more than half of the beginners in their first C class give up when handling pointers/arrays - it's not because the concept is hard, but because they have no idea what the "memory" in the computer actually is and how it works. You're left with a naive analogy of home addresses and phone numbers, but it really doesn't give pointers justice (especially when dealing with arrays and dynamic memory!) Every student learning C should have a basic idea about the stack and the heap, how function calls work, and how assembly code is executed, in order to get the full picture.

Anyways, the problem C++ has for beginners is that the language tries to obscure the already hard to understand low-level behavior with high-level concepts (to be fair, that is the language's ultimate goal: to provide a high-level abstraction for low-level code.) So maybe good for your second/third language, but definitely not your first.

Re:Initialization in C++ is Seriously Bonkers by shereadsthenews on Saturday January 05, 2019 @01:57PM (#18833485)
> I always think C/C++ is not a good first language to teach, because you need to understand some general concepts about computer systems before diving in.

Some believe that it's important to teach those things about computer systems first. To anyone who knows how the machine works it's pretty obvious why a primitive stack variable is uninitialized: initializing them would cost a store which would in most cases be pointless. People use C and C++ because they want all of the performance the machine has to offer, and usually more. Stuffing the program full of immediate value loads and stores would make it huge and slow. C++ is already cursed with enough pointless stores, for example initializing the buffer of a string just after resize and just before copying something else into the same memory. We don't need more of these things.

The author then goes on to complain at length about {} initializers in C++11, which everyone recognizes as problematic, and which has been partially fixed in C++14. This has basically nothing to do with the first part of the article.

Re:Initialization in C++ is Seriously Bonkers by williamdclt on Saturday January 05, 2019 @03:12PM (#18833935)
I learnt C as a first language, and those computer sytems concept were explained as we go. It's not that hard to understand what memory is and that variables values are stored there, and I've had no problem with pointers.

And the big advantage is that when you understand those concept and pointers, there's no magic in other languages (value/reference parameters, objects, functions as first-class citizens)

Re:Initialization in C++ is Seriously Bonkers by maxxxxx on Saturday January 05, 2019 @03:22PM (#18833980)
Totally agree. Knowing C and a little assembly takes out the magic from other higher level languages. That's a good thing.
Re:Initialization in C++ is Seriously Bonkers by angry_octet on Saturday January 05, 2019 @07:08PM (#18835303)
Monads are still a little magical though.
Re:Initialization in C++ is Seriously Bonkers by Gibbon1 on Sunday January 06, 2019 @12:58AM (#18836832)
I keep thinking that C could support monads with a little work.
Re:Initialization in C++ is Seriously Bonkers by geezerjay on Monday January 07, 2019 @05:12AM (#18844080)
As I see it, adding lambda/anonymous functions would have a transformative impact on the whole language. Adding them to C++ had a similar impact although the language offered some ways to get around the limitation.
Re:Initialization in C++ is Seriously Bonkers by maxxxxx on Monday January 07, 2019 @01:04PM (#18847947)
Very true. When I look at C# pretty much all the cool stuff they have added relies on lambdas and closures. Same for JavaScript. It's the one feature that enables a ton of other features.
Re:Initialization in C++ is Seriously Bonkers by MikeLui on Sunday January 06, 2019 @10:03AM (#18838632)
"Programmable semicolons."
Re:Initialization in C++ is Seriously Bonkers by int_19h on Saturday January 05, 2019 @09:51PM (#18836205)
On the contrary, properly teaching pointers can do wonders to help people understand how memory is structured.

C and C++ are horrible academic languages for other reasons - the original design is just too much of a hack to begin with, and then there's decades of legacy backwards compatibility with it in all newer developments. Syntax is ugly and inconsistent, doing things right is often harder than doing them wrong, there are many features and exceptions that are only there for historical reasons, and standard library is very eclectic in terms of what is and isn't included (from a modern perspective). But take something like Modula-2, and pointers aren't a problem.

Re:Initialization in C++ is Seriously Bonkers by ChrisSD on Saturday January 05, 2019 @02:29PM (#18833667)
I think it's better to teach basic assembly before C. Using memory addresses makes so much more sense in assembly.

But for a first language I'd want to use something like Python or Javascript or even a toy language. It simply needs to be something where some basic, high level concepts can be taught without worrying about the details.

Re:Initialization in C++ is Seriously Bonkers by ahartmetz on Saturday January 05, 2019 @04:40PM (#18834446)
Yeah, there is really no need to be scared of assembly. It is easy to learn because there is not much to it. Only writing nontrivial programs in assembly is hard, and you don't need to do that to understand what's going on behind the scenes in compiled code.
Re:Initialization in C++ is Seriously Bonkers by a1369209993 on Saturday January 05, 2019 @05:37PM (#18834724)
> Only writing nontrivial programs in assembly is hard

It's not even really hard, just crushingly tedious and error-prone. You could also write all your programs on 80-column punch cards or with (1)ed, but why bother if there isn't some technical reason why a text editor isn't available?

Re:Initialization in C++ is Seriously Bonkers by shams93 on Saturday January 05, 2019 @02:54PM (#18833820)
Yeah even in the old days Pascal was the language of choice for beginners. Now pythin holds that position although some schools teach java or c# as a first language many use python these days.
Re:Initialization in C++ is Seriously Bonkers by waynecochran on Saturday January 05, 2019 @02:19PM (#18833615)
In embedded assemblers I have used (TMS34010), the BSS section is uninitialized when the program is loaded (I helped write the OS). When I wrote embedded C, the added C runtime code that executes (before main() is called) zeroes out the BSS section (the OS has nothing to do with it). In other words, it is the C runtime that is responsible for initializing, not the OS.
Re:Initialization in C++ is Seriously Bonkers by ajross on Saturday January 05, 2019 @02:21PM (#18833625)
I think you're the fourth person jumping in to quibble with my "bss is zeroed by the OS" statement by snarking about "Ah hah! But what if you YOU ARE the OS?!".

Yeah, I know. I live in that world too. I don't know that it's particularly relevant. The C standard is written to a norm of a Unix userspace environment, and that's clearly where the linked article is working.

Re:Initialization in C++ is Seriously Bonkers by waynecochran on Saturday January 05, 2019 @02:55PM (#18833824)
It’s the C runtime that zeros it, not the OS. That’s my main point. The OS may initialize too, but that is outside the standard.
Re:Initialization in C++ is Seriously Bonkers by ajross on Saturday January 05, 2019 @03:04PM (#18833888)
On oddball platforms it might be (though I think there's some quibbling as to whether the C runtime in such an environment is really distinct form "the OS"). It's not on Linux. The .bss segment becomes an anonymous mmap which is zeroed by the kernel when first accessed. Glibc never touches it.

(Edit to correct: obviously glibc "touches" .bss because it has its own static variables. But there's no "zero .bss" step in crt0.o)

Re:Initialization in C++ is Seriously Bonkers by monocasa on Saturday January 05, 2019 @03:42PM (#18834114)
I mean, there's probably more shipped units of "oddball systems" than there are of Unix-like multi process systems that have to wipe segments like .bss vracuse of their security model. So it's not like it's some pedantic corner case like you're implying.

And there are other parts of the C standard that would just declare 'implementation defined', so the standard doesn't have to say static duration is initialized just because that's what multi process systems do.

Re:Initialization in C++ is Seriously Bonkers by waynecochran on Saturday January 05, 2019 @07:00PM (#18835259)
./libgcc/config/nds32/crtzero.S

    .L_bss_init:
        ! clear BSS, this process can be 4 time faster if data is 4 byte aligned
        ! if so, use swi.p instead of sbi.p
        ! the related stuff are defined in linker script
        la  $r0, _edata     ! get the starting addr of bss
        la  $r2, _end       ! get ending addr of bss
        beq $r0, $r2, .L_call_main  ! if no bss just do nothing
        movi    $r1, 0          ! should be cleared to 0
    .L_clear_bss:
        sbi.p   $r1, [$r0], 1       ! Set 0 to bss
        bne $r0, $r2, .L_clear_bss  ! Still bytes left to set
Re:Initialization in C++ is Seriously Bonkers by ajross on Saturday January 05, 2019 @08:08PM (#18835602)
How does finding some uncompiled sample code someone added to gcc for an architecture no one has heard of refute the point that glibc on Linux implements bss with an anonymous mmap?
Re:Initialization in C++ is Seriously Bonkers by waynecochran on Sunday January 06, 2019 @12:26AM (#18836720)
Not meant to refute, just sample code on the C runtime zeroing the bss section. You'll find this for a variety of systems, this was just one of them...
Re:Initialization in C++ is Seriously Bonkers by monocasa on Saturday January 05, 2019 @10:59PM (#18836487)
Rather than pointing to Linux over and over, let's look at Win95. It kind of comes from a 'fuck local security' standpoint (everything mmaped is in one global space mapped into all processes), and still clears bss because that's what the spec expects, and like a lot of embedded systems is fully spec compliant.
Re:Initialization in C++ is Seriously Bonkers by gamma-male on Saturday January 05, 2019 @09:40PM (#18836140)
The OS does initialize it, so if you’re writing code for linux in any languages, or even in assembly, you won’t be able to spy on that retrieved memory.

Now C might want to do it too, but bare metal stuff is not necessarily compliant C so that doesn’t matter much.

Re:Initialization in C++ is Seriously Bonkers by monocasa on Saturday January 05, 2019 @10:54PM (#18836473)
(Having been the lead for an RTOS) it matters less what the spec says, and more what the compiler expects. So like, you can ignore kill(3) by just not calling it. Patching the compiler to not depend on zero initialized .bss is way harder, and it's just easier to clear it yourself pre main.
Re:Initialization in C++ is Seriously Bonkers by ben0x539 on Saturday January 05, 2019 @05:34PM (#18834713)
You're certainly correct, but I don't understand why you're phrasing this as an objection rather than as a rationale for how the language is specified.

Personally, I enjoy that the C standard makes a bunch of guarantees that I can use for my reasoning about correctness. Of course I can only get so far reasoning in abstract, language-defined terms and ignoring the execution environment, but where it is sufficient, being able to forget about operating system minutiae is certainly a relief.

Since the main thrust of the article is that C++'s language-imposed rules are overly complicated, restricting the perspective to the language specification seems reasonable.

Re:Initialization in C++ is Seriously Bonkers by amluto on Saturday January 05, 2019 @01:52PM (#18833446)
> The .bss segment has been zeroed, for obvious reasons, since the advent of modern linkage.

For your amusement: in the Linux kernel, at least on x86, .bss isn’t initialized when the kernel is loaded. Instead, the kernel memsets it to zero a little later. I don’t know why.

Also, because all this stuff predates any concept of security, there is no read-only equivalent of .bss in most systems, meaning that you get suboptimal code for:

const int i = 0;

Re:Initialization in C++ is Seriously Bonkers by int_19h on Saturday January 05, 2019 @09:57PM (#18836244)
Why would the code for "const int i" be any different from the code for "int i"? The Standard doesn't require the variable to be allocated in an immutable memory area. It just says that if you do anything to change its value, the result is undefined behavior. And actually changing the value in a way that would be observable via the const variable is a valid subset of undefined behavior.
Re:Initialization in C++ is Seriously Bonkers by AnimalMuppet on Saturday January 05, 2019 @03:06PM (#18833904)
The optimal code for const int i = 0; is for the compiler to inline its uses, and for there never to be any storage allocated at all.

;-)

Re:Initialization in C++ is Seriously Bonkers by comex on Saturday January 05, 2019 @06:05PM (#18834918)
That works unless you use &i somewhere.
Re:Initialization in C++ is Seriously Bonkers by jstimpfle on Saturday January 05, 2019 @02:18PM (#18833609)
It's hard to imagine many situations where you need to give a name to the constant value 0. And think how "optimal" it would be if there were many and we had a read-only BSS! We could cheaply get a huuuge section full of constant zeroes.

I think you can in fact realize the idea in PECOFF, by the way. I still need to figure out some aspects to it these days (it seems a bit arcane and maybe Windows doesn't follow the spec very well). But in any case PECOFF has this notion "VirtualSize" (size of section in running program) and "SizeInFile" (size of the prefix of the section that should be filled with contents from the executable file). If SizeInFile is smaller than VirtualSize then the rest of the image gets filled with zeroes I think.

Re:Initialization in C++ is Seriously Bonkers by userbinator on Saturday January 05, 2019 @02:29PM (#18833668)
But in any case PECOFF has this notion "VirtualSize" (size of section in running program) and "SizeInFile" (size of the prefix of the section that should be filled with contents from the executable file). If SizeInFile is smaller than the rest of the image gets filled with zeroes I think.

Correct. A common and low-hanging-(more like "lying on the ground")fruit optimisation for PE files is to reorder and realign the sections such that all the 0s are at the end, in which case they can be "cut off" by setting those header fields appropriately and not waste storage space.

Re:Initialization in C++ is Seriously Bonkers by ajross on Saturday January 05, 2019 @02:26PM (#18833654)
> I think you can in fact realize the idea in PECOFF, by the way.

You can express it in ELF too, with a NOBITS segment with ALLOC but no WRITE flag. Whether that works or exercises bugs in the dynamic loader is an open question.

Re:Initialization in C++ is Seriously Bonkers by amluto on Sunday January 06, 2019 @11:11AM (#18838979)
On Linux (in the kernel image), it exercises bugs in the dynamic loader. I tried it once :)
Re:Initialization in C++ is Seriously Bonkers by rabidrat on Saturday January 05, 2019 @01:58PM (#18833489)
The OS program loader is who allocates pages to .bss and initializes them to zero. In the case of an OS, who would do that initialization? At best it would be the bootloader. Initialization during kernel_init() before using any globals is acceptable too.
Re:Initialization in C++ is Seriously Bonkers by Gibbon1 on Sunday January 06, 2019 @01:14AM (#18836873)
Having seen both sides of this, people are arguing about the proper way to skin a cat. The standard only cares the cat be skinned not how.

On OS it's done by the OS for security and performance reasons. One you don't want people to snoop on memory freed from other processes. Two the OS can use the MMU to map in previously zero's pages of memory on demand, so you don't need to actually zero the entire .BSS section on startup.

On a bare metal system usually it's done either in assembly (or more cheezy in C) + linker magic.

Re:Initialization in C++ is Seriously Bonkers by atombender on Saturday January 05, 2019 @02:35PM (#18833709)
I don't think we should pretend that any of this was planned out. The reason the C standard is like it is because it doesn't just specify the best possible version of C that can exist, but because it encodes historical behaviour.

It's possible to post-rationalize those decisions, but as I understand it, there's no particular reason why .bss has to be initialized -- it just happens to be the way Unix has worked since forever.

With modern static analysis, there's probably no performance benefit to not initializing stack variables that are read before they're written?

Re:Initialization in C++ is Seriously Bonkers by jstimpfle on Saturday January 05, 2019 @02:48PM (#18833782)
> With modern static analysis, there's probably no performance benefit to not initializing stack variables that are read before they're written?

Not really relevant because that's a bug.

But the common thinking "let's always default-initialize stack variables because the compiler will make it efficient anyway" is clearly "sufficiently smart compiler" thinking. Implicit default initialization will never be 100% as efficient as simply not requiring initialization.

Plus, I like the error messages I can get, sometimes, with no default initialization. The compiler can statically detect some uninitialized reads. It cannot do that if all variables are implicitly initialized. In many other cases at least one can be quite certain to experience random crashes that let one track down the bad read rather quickly.

In other words, implicitly initializing to zero normally just hides logic bugs. It doesn't make them go away.

Re:Initialization in C++ is Seriously Bonkers by int_19h on Saturday January 05, 2019 @09:54PM (#18836226)
A better idea is to force the initializer, and require some special syntax if you really want an uninitialized variable. E.g. if a language uses underscore as a syntactic wildcard, then it could be something like:

   int x = _;
The vast majority of variables can and should be initialized when they're declared (and often don't ever change after, so const is a good idea too). This is especially so in C++, which is less likely to return values via references/pointers these days (with tuples and uniform init for returning structs).
Re:Initialization in C++ is Seriously Bonkers by Joky on Saturday January 05, 2019 @05:48PM (#18834799)
Note that clang just got a change to experiment with this: https://reviews.llvm.org/rL349442
Re:Initialization in C++ is Seriously Bonkers by jstimpfle on Saturday January 05, 2019 @06:07PM (#18834934)
Doesn't seem to me like a statement that variables should be implicitly initialized.

It seems like a workaround around insanity with respect to UB (where compilers fail to notify the programmer that they statically detected a logic bug, and instead go on with compiling, making crazy optimizations based on the wrong assumption that the logic bug was never there).

Re:Initialization in C++ is Seriously Bonkers by Joky on Saturday January 05, 2019 @06:54PM (#18835233)
> Doesn't seem to me like a statement that variables should be implicitly initialized.

Not at all. I also believe that we shouldn't hide logic bugs, but the problem with this class of bugs is how they are hard to catch: forcing the initialization can at least make the behavior more consistent across execution of the same program (avoid the rare sequence of condition that will clobber the value the right way before you use it). For some specific application this may be an OK tradeoff for release builds.

But to clarify why I posted this, I was just trying add one piece of data to this part of the thread of discussion

>> " With modern static analysis, there's probably no performance benefit to not initializing stack variables that are read before they're written?" >"Implicit default initialization will never be 100% as efficient as simply not requiring initialization"

Actually we don't know the exact impact, it is likely codebase dependent, but this patch in clang will allow to experiment with various tradeoffs.

> where compilers fail to notify the programmer that they statically detected a logic bug

Compilers (at least clang) won't detect a logic bug without noticing the programmer. You have warnings for this.

The optimize just "assumes" that there is no logic bug but can't reason about the logic:

{ int a = 1; foo(&a); } int b; bar(&b);

Can I optimize toward:

int a = 1; foo(&a); bar(&a);

If we assume that there is no logic bug, then it seems like a valid transformation to me. But if bar reads it parameter before writing to it, then this optimization makes foo impacting bar.

Re:Initialization in C++ is Seriously Bonkers by jstimpfle on Saturday January 05, 2019 @07:26PM (#18835407)
Thanks, that's insightful!
Re:Initialization in C++ is Seriously Bonkers by Gibbon1 on Sunday January 06, 2019 @01:05AM (#18836851)
I'll tell you I'd rather live in the current world where the compiler emits a warning 'foo may be uninitialized' than the world we are heading into where that enables a half assed optimization that speeds up a ubenchmark on an architecture no one uses anymore.