8 ms·
> If you want to avoid C++ that's great, but to argue for C over it is insanity rooted in nostalgia. Did you know that code in C++ can run outside of main()?
by bb88 9y ago
> If you want to avoid C++ that's great, but to argue for C over it is insanity rooted in nostalgia.
Did you know that code in C++ can run outside of main()?
I used to be a C++ believer, and advocated for C++ over our companies use of Java.
One day, they decided they wanted to "optimize" the build, by compiling and linking objects in alphabetical order. The compile and link worked great, the program crashed when it ran. I was brought in to figure it out.
It turned out to be the C++ "static order initialization fiasco":
https://yosefk.com/c++fqa/ctors.html#fqa-10.12 https://yosefk.com/c++fqa/ctors.html#fqa-10.12
If you've ever seen it, C++ crashes before main(). Why? Because ctors are getting run before main(), but before other dependent statics have been constructed.
Changing the linking order of the binary objects fixed it. Remember nothing else failed. No compiler or linker errors/warnings at the time, no nothing. But one was a valid C++ program and one was not.
You might think that is inflammatory, but I considered that behavior insane, because main() hadn't yet even run, and the program cored leaving me with trying to figure out what went wrong.
>> Furthermore, you don't want exceptions in kernel code.
>Nobody said anything about C++ throw/catch exceptions.
I'd like to add that if you're finding yourself restricting primary language features (e.g. templates, statics ctors, operator overloading, etc.) because the implementation of those features are bad, maybe using that language is the wrong choice for the project you're working on.
After I read the C++ FAQ lite [1] and the C++ FQA [2], I realized the determinism that C provides is kind of a beautiful thing. And yes. For a kernel, I'd argue C over C++ for that reason.
[1] C++ FAQ Lite: http://www.dietmar-kuehl.de/mirror/c++-faq/ http://www.dietmar-kuehl.de/mirror/c++-faq/
[2] C++ Frequently Questioned Answers: https://yosefk.com/c++fqa/ https://yosefk.com/c++fqa/
- gmueckl 9y agoWell, if your main argument against C++ is undefined order of static initialization amd that it caught you by surprise, then I'd counter that by saying that you do not know the language very well. This is very well known behaviour. I think that there are stronger arguments against C++: the continued presence of the complete C preprocessor restricting the effectiveness of automatic refactoring, the sometimes extremely cumbersome template syntax, SFINAE as a feature, no modules (yet!)... Still, C++ hits a sweet spot between allowing nasty hardware-related programming hacks and useful abstractions in the program design.
- bb88 9y ago> ...then I'd counter that by saying that you do not know the language very well. This is very well known behaviour. So parsing your sentence. I'm right, and you're blaming me for not knowing a language as expertly as you. I can live with that. Edited to add: I admit it's a little snarky perhaps, but the c++ standard is 1300 pages long. It took my browser in 2018 1 minute to open it. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n379... I really do not have time to read a document like that to figure out whether or not that behavior is spelled out in the standard. So yes, I'll let you be the expert on this.
- gmueckl 9y agoSorry if the statement offended you. It came from the experience that I so far haven't encountered anyone who seriously uses C++ and does not know about the undefined order of static initialization. Also, I haven't yet had a situation where this was a big deal. There are worse pitfalls than unstable order with static initializers specifically. If you dynamically load shared libraries at runtme on Linux, you risk static initializers being run multiple times for the same library. This is platform specific behavior that is AFAIK present on other UNIX systems as well and I'm certain that you won't find that in the standard.
- bb88 9y ago> Sorry if the statement offended you. It came from the experience that I so far haven't encountered anyone who seriously uses C++ and does not know about the undefined order of static initialization. Water under the bridge. While I did say I was brought in to fix it, what I didn't say was that the group's management thought that Java coders could code in C++. D'oh.
- deleted 9y ago[deleted]
- Shikadi 9y agoIt's worth noting that most language standards are of similar length
- pjmlp 9y agoWell, let me tell you that C suffers from the same issue of running code outside main(). It is funny how many issues people blame on C++ that are usually inherited from C semantics compatibility, or existing C extensions at the time C++ started to get adopted.
- bb88 9y agoNo no no no no. This is a C++ problem. As much as you want to blame this particular problem on C, C handles this the right way. Let's try to write the equivalent of this error in C: int myfunc() { return 5; } static int x; static int y = 4; static int z = myfunc(); int main() {}; Compiling that in gcc gives me: main.c:8:16: error: initializer element is not constant static int z = myfunc(); ^~~~~~ And it makes sense, C just wants to do a memcpy() to initialize the static variables. In C++, the only way the class is initialized is if the ctor is run. And that means running the ctor before main(). Edited to add: You're correct that 5.1.2 does not specify memcpy() as a form of initialization. But see my reply below about C11 and static storage classes.
- kuschku 9y agoThe same issue always occurs where you have static constructors that are not constant. That's why it gives you a compiler warning, and why your IDE marks it in yellow. The same issue occurs in any language with static constructors, including Java.
- pjmlp 9y agoNow try that with other C compilers as well, or without using static. Also add common C extensions into the soup like constructor function attributes. Finally ISO/IEC 9899:2011, section 5.1.2. "All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment." Don't mix what your compiler does, with what the standard requires. Doing so only leads to unportable programs and misunderstandings.
- halfer53 9y agoEven in C, the program doesn't start in main(), Glibc actually wraps a function called _start() before the main(), something like this void _start(){ / bla bla / exit(main(argc, argv)); }
- surfmike 9y agoC++ gives you a lot of rope to hang yourself but style guides help constrain the language to deal with issues like the one you described: https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables https://google.github.io/styleguide/cppguide.html#Static_and...
- bb88 9y agoThat's great for google and greenfield projects, but if you have people that insist that enum's should be static classes, god help you.
- taneq 9y agoThe first thing I thought of was http://lbrandy.com/blog/2010/03/never-trust-a-programmer-who-says-he-knows-c/ http://lbrandy.com/blog/2010/03/never-trust-a-programmer-who... The better I get at C++, the less of it I actually use.
- bb88 9y agoI've not seen that. But I think that graph matched my experience with C++. I just stopped right before "We Need Rules."
- exDM69 9y agoThe Singleton pattern can be used to fix the order of static constructors. I think that this is the only reasonable use for the singleton pattern (which is just a global variable in disguise). In my opinion, it's better to not rely on static constructors for anything non-trivial (singleton or not). They can be such a pain in the ass to debug.
- aepiepaey 9y agoThis made me think of segmentation faults caused by stack overflow due to allocating an array with too many elements on the stack, which is also "fun" to debug until you learn about that class of problems. That applies to both C and C++ though.
- pjmlp 9y agoAnd one of the reasons why the VLAs introduced in C99 became optional in C11.