Initialization in C++ is Seriously Bonkers
1–10 of 130 posts
Re: Initialization in C++ is Seriously Bonkers
#2No, 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
#3> [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…
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
#4> [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…
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
#5 #include
struct A {
A(std::initializer_list l) : i(2) {}
A(int i = 1) : i(i) {}
int i;
};
int main() {
A a1;
A a2{};
A a3(3);
A a4 = {5};
A a5{4, 3, 2};
std::cout
which outputs: 1 1 3 2 2
he claims to be mysterious but is actually pretty reasonable.In the case of:
a1: There is no initializer list in the variable declaration, so ctor 2 is called.
a2: An empty initializer list should reasonably behave like a default constructor, and a default constructor should be more efficient than processing an initializer_list, so ctor 2 is called. In general, the constructor with the matching number of arguments and correct types is preferred over initializer_list constructors. Makes sense, being able to specialize on number and type of arguments is more powerful than a design where a single initializer_list ctor invalidates all other ctors.
a3: No list, ctor 2 is called.
a4: Non-empty init list and no specialized non-init-list ctor, so ctor 1 is called.
a5: Several-variable init list and no overriding 3-variable constructor with matching types, therefore ctor 1 is called.
Complex? Maybe, but that's what you get with C++: very fine control of program semantics, benefit being expressive libraries. No other language fills this niche that I'm aware of.
I agree that C++ isn't a good language to teach in a CS 101 class. But no other single language is good either. The goal of CS 101 is to not make students give up before they get hooked, and that can happen because the material is too challenging or not challenging enough. For people in the former category, give them a scripting language and visual feedback, like Lua + Garrysmod. For the latter, give them assembly, haskell, C, C++ (teaching it like "C with templates" not "C with classes").
Re: Initialization in C++ is Seriously Bonkers
#6> [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…
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 analo…
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
#7> [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…
> 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 sub…
Re: Initialization in C++ is Seriously Bonkers
#8> [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…
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
#9In my view this author falls into the camp of people calling C++ a mess because it gives them too much control when they ask for it. One of his examples which he calls "The Abyss": #include struct A { A(std::initializer_list l) : i(2) {} A(int i = 1) : i(i) {} int i; }; int main() { A a1; A a2{}; A a3(3); A a4 = {5}; A a5{4, 3, 2}; std::cout which outputs: 1 1 3 2 2 he claims to be mysterious but is actually pretty r…
Congrats on successfully summarizing the complaint.
It's not mysterious, but it's gratuitously complex. And this is only variable initialization.
Re: Initialization in C++ is Seriously Bonkers
#10In my view this author falls into the camp of people calling C++ a mess because it gives them too much control when they ask for it. One of his examples which he calls "The Abyss": #include struct A { A(std::initializer_list l) : i(2) {} A(int i = 1) : i(i) {} int i; }; int main() { A a1; A a2{}; A a3(3); A a4 = {5}; A a5{4, 3, 2}; std::cout which outputs: 1 1 3 2 2 he claims to be mysterious but is actually pretty r…
> Complex? Yes, but that's what you get with C++: Congrats on successfully summarizing the complaint. It's not mysterious, but it's gratuitously complex. And this is only variable initialization.
If just setting integers is this complicated, what do you expect to happen when you are trying to solve real problems?