Coding Tech - 2018-02-18
I've spent the last few years watching Facebook's C++ codebase grow by several orders of magnitude. Despite constantly improving abstractions, constantly improving tooling, frequent internal courses, and ongoing internal discussion, there are bug-patterns we simply cannot stop from being reintroduced into our code. My hope is to show some of the most common (and infamous) bugs in our history, and the surprising complexity that arises in some apparently simple situations. This talk serves the dual purpose of educating the intermediate (and perhaps the occasional advanced) C++ programmer about some really nasty common pitfalls, as well as serves as a plea to experts to help further improve the language, libraries, and best practices to help educate and eradicate some of these problematic patterns. EVENT: CppCon 2017 SPEAKER: Louis Brandy: Engineering Director, Facebook PERMISSIONS: CppCon Organizer provided Coding Tech with the permission to republish this video. Additional material for C++ learners: https://amzn.to/2TquTgE Murach's C++ Programming https://amzn.to/2Tqx2ZK. C++ in One Hour a Day, Sams Teach Yourself (8th Edition) https://amzn.to/2Fk1CiP A Tour of C++ (2nd Edition) (C++ In-Depth Series) https://amzn.to/2OjPToz C# Programming Illustrated Guide For Beginners & Intermediates: The Future Is Here! Learning By Doing Approach
33:35 "Do a code search" - I just did and found 2 improper uses of a RAII class just like that (Chrome browser code). Damn...
A lot of problems/bugs are not caused by C++ itself, but by the way STL or other template sets are written. C++ is a great language, but programmers misuse it. Sometimes, instead of simply writing a = b + c; they need a template...
facebook is a bug itself
8 years ago everyone slated me and called me crazy because i knew facebooks true intentions, now it's completely normal.
..
it's a feature!
Facebook has had some good things come out of it though, like this talk.
Facebook never had anything. Apart from social engineering, brain washing, selling your data to corporates and changing society for the worst.
Its not as toxic as twitter.
The C in C Programming stands for curiously recurring bugs. This is a fact.
the c in c++ stands for "cache miss" actually
And "S" in C stands for "Sanity"
and this must be coming from some functional asshole?
I've added this (really good, BTW) talk to my bookmark list "reason to use Rust".
Can I have a link to that (is it a Youtuber playlist?)?
Dawid Ciężarkiewicz
C++ was my first language
"for my money I want better tools" perhaps not using C++ ?
7:14 using namespace std
It really doesn't render the namespace useless. You can still use the "::" with nothing before it to explicitly qualify things. there really is no downside in the final binaries. Just don't do it in headers, to avoid polluting the namespace of source files that include your headers.
I usually just do it from the top of source files, because at that point, no one will care. Typically, if you are distributing a prebuilt library, the source files aren't distributed with it, so it matters even less.
If there is a namespace collision, just use explicit qualification, just like you would have to do without the namespace. You might want to avoid using namespaces if there are a lot of collisions, though. You can also "use" specific symbols from a namespace, which might make more sense.
It is not about binaries.
It is about making unnnoticed programming mistakes. A namespace is a tool to guard you. By introducing a
using namespace std;
you effectively shut down the guard.
You can use it in .cpp files but you shouldn't in header files. The problem is that if anyone includes your header file and you have using namespace std, they will include that part too. If they use some other string library for example, the name "string" will be multiply defined and their code will not compile.
cpp files are not included so it's ok, but I still don't use it, because I actually want to see the exact type and implementation and not wonder if I used std string or some other string, then hover my mouse over it in the ide or scroll up in the file to all my using statements.
Well, that is what's taught.
@Kshitij Jhalak Well said
42:50 If you can't write the bug in the first place, that's better than any other options.
Language designers and library designers should design to prevent errors like this from being possible in the first place.
Guy Smith That’s more typical of C and C++ programmers than programmers in general.
C-based programmers are dangerous. In every literal sense.
17:40
Oh neat, maybe he'll say something interesting about how volatile is treated by the compiler
17:56
......
There are people WHO THINK THAT!?!?!? jfc
I thought high level languages were supposed to make programming easier....
In which universe is c++ high level?
c++ is by definition high level. If you think it doesn't make life easier, try writing a big program in assembly.
Ciccio&Bombo …or try writing a big program in Ruby/Python/Javascript. ;-) Mind you, web pages aren't big programs.
“That’s good if you know that, but they don’t.” Have you considered telling them?
i got nausea from watching a camera move around for 40 minutes
Look at the slides then.
30:25 man with vision
Mark Zuckerberg, Sheryl Sandberg. Two biggest bugs.
They're obviously lizards, not bugs. They probably eat the bugs.
42:47 is literaly an expanding brain meme
30:00 Checking on visual studio xD
Eek, the lock (whatever) bug! Default constructors and death!
Love your talk. Thanks!
Very helpful talk! thanks!
35:50 "But the rule is; if it's ambiguous"... Well stop right there. Ambiguity is ALWAYS a problem. No code should ever be ambiguous. That should really be fixed in the language.
Welp, even JavaScript(*gasp*) gets a strict mode.
If I can have only one thing in my life that would be C++ without any of those stupid surprises.
What C++ could really use would be an alternate syntax redesigned from the ground up which is API-compatible with regular old C++, but which is at least syntactically less crufty and is a strict subset which eliminates many of the features that didn't age well.
+BosonCollider: There are a number of places where the designers of C and C++ decided to describe things in a simplistic fashion which fails to describe how things should actually work, rather than adopting a very-slightly-more-complicated model that would end up being easier than the bodges required for the "simplistic" model. The model of PODS have dynamic types and lifetimes apart from that of the enclosing storage, the way non-PODS objects do, for example, is a fundamentally broken, and totally unnecessary. Far simpler and cheaper to build a definition of aliasing that recognizes that a reference that isn't used in any fashion during a particular execution of a function or loop doesn't alias anything during said execution, and that a reference that is derived from another doesn't alias the first unless it is used to address a byte after either (1) the parent addresses a byte in conflicting fashion, or (2) execution enters a loop or function wherein the parent will address that byte in conflicting fashion. No more need for "dynamic types", nor even the "character-type exception". The model would be different from the model used for non-PODS objects, but it would actually fit the way operations on untyped storage actually work.
It's not really ambigous, it only looks like that at first. Since it will always count as a declaration it is clearly defined, you simply need to think about more than 1 rule at a time.
+MsJavaWolf: When C89 was written, the authors didn't think there would be a practical difference between actions which were actually mandated by the Standard, and useful actions which that were processed identically by all present implementations and were expected to be processed by all non-capricious future implementations, even without a mandate. They thus saw no need to resolve places that were ambiguous between those two possibilities. I don't think they imagined that such ambiguities would lead to decades of conflict between compiler writers who veto any effort to make the standard unambiguously block their "optimizations" and programmers who veto any effort to make the Standard unambiguously invite such behavior. The net result is that ambiguities which were causing confusion 25 years ago are still unresolved.
Perhaps, though, the real solution is for the public to recognize that the Standard is designed to allow implementations which are intended only for specialized purposes, to behave in ways that would make them unsuitable for any other. The fact that a program for some purpose won't work with an implementation that doesn't claim to be suitable for such purpose doesn't imply that either is defective in any way. A program cannot truthfully claim to be suitable for most purposes, however, without behaving predictably in many cases where the Standard would impose no requirements.
at 43:15 he goes full Anatoly Dyatlov mode
40:00 - -Wshadow is awesome. I turn it on everywhere, and always use the narrowest-possible scope for every variable. I know that when my code is warning-free, I have a much smaller chance of side-effects from reused variables. Also, I can easily break sections into new functions, because they are already tightly scoped. It's 2 birds with 1 stone.
Nice talk and especially the compilation of std::string(foo) was a bit unexpected.
Seems like worrying about extraneous copies is a bug except when it actually matters.
Why even use Map instead of a struct?
Well, it explains why facebook (site and app) doesn't always work as expected. Well, pretty much all the time it doesn't.
I thought I knew C++ pretty well. I'm now realising more and more what an incoherent f-up of a language it is.
@himselfe can you give some examples please? Thanks.
@richard vaughn Couldn't be more correct. There are no bugs in C++, at least.. not many. People just code wrong.
I'd the say it's more likely that the premise is wrong..
Indeed it has very sharp edges like accepting the std::string(foo) and difficult rules especially when using templates (e.g. two phase lookup). Still I love it for all the other reasons (e.g. zero cost overhead; performance; value based).
@Leonardo Ponzoni Oh yes, you do have to think abour memory management in Java pretty hard, unless your programs are really short lived. ;-)
I thought this video is supposed to explain CRTP.
How did you win the volatile bool argument?
Clang FTW
Clang FTW
It's 2018! You should know that C++11 introduced map.at() method to access elements from const map
My thoughts exactly, but then he says "but people don't know that". if that is his attitude, then he is lost, since there will be always a better idiot for his idiot proof mitigations...
The point of software engineering is to make programming unbreakable even for idiots.
We use safety belt not because we don't drive safely, but there ALWAYS an idiot who will slam his car in your face. In tech land, stupid mistake like those could cost entire company's career.
Well the thing I kept asking is: Why the fuck would the square bracket operator insert anything into the map? Can anybody explain the reasoning behind that?
For convenience. For example if you're counting the number of occurrences of each character in a word, you can simply do:
map<char, int> mp;
for(char ch : str) ++mp[ch];
its a valid L-value so it has to capable of holding the memory, this causes value initialization, if the version of C++ has it; for example, in C++99, it could just be random memory (all compilers of C++99 value initialize, but it was not a standard until C++03).
My life was a joke...
Won't r value reference fix the reference bug in 16:00?
const ref
All bugs he presented really are trivial. I'd see from reading. I think it may be because I took the time to learn C++ from TheCppPL book and reading the Standard. You can figure out the language most common grammar completely with that setup. It took me 8 years after actually programming in C++ starting in high school to actually learn. Boy, it was worth it.
That map problem is not a problem in Rust with ownership semantics and the entry pattern.
recurring bug means recursion bug
OMG, it is just social network. Not a roket science. I don't understand how someone can feel any encourage to work on Facebook.
Just a big ad for Rust language.
Obviously if you are beginner, go with Go, but it's a little bit different purpose language.
Rust is not that hard to learn if you have experience in C or ML-based languages. What you get for that is a real systems programming language with a much more modern expressive type system.
The main issue with Rust imho is that the types can get pretty verbose (much like C++). Hopefully this will get better with language features like impl trait/existential types and good IDE's. But from what I've heard it is very nice to use in large projects with big teams.
Go is nice, but it has a Garbage Collector. You do understand that a Garbage Collector is just a band-aid solution to a core problem? Right? It's a SHIT solution, but it is sometimes good enough. But it doesn't solve the CORE problem of memory management, so it's still shit.
Rust is for people that aren't careful with their programming, its the equivalent of spoon-feeding a child. I really think its the modern equivalent of pascal, which was a pretty horrible language.
Rust programmers wish to be careless - but not because they care less.
Rust excludes whole classes of bugs because it does not allow you to write them, they are errors at compile time. By acknowledging you and everyone else is fallable, it is comforting to know the compiler ensures your code to be within certain bounds so it can make guarantees about the compiled code that other languages cannot. Consequently many bugs mentioned in the presentation cannot exist in your Rust code and thus do not get shipped. From a caring point of view Rust is quite a sound choice.
You may find it harder to get your thing compiled, maybe, but your program will never segfault nor will it have data-races.
You can and will still write bugs and your program may be fed garbage but it is easier to reason about your code if you have less to worry about.
I’ll respect you skill asa programmer but I’m afraid I disagree with the company of choice but money money. 🤷♂️
He sold his soul for that $. Facebook started from thievery.
Chris McCaulley if I saw him begging on the street homeless I’d stop and give him a thumbs up
+Freakinkat Gaming That is just hilarious. You made my day lol.
Chris McCaulley 😸
12:35 BAN MUTABILITY, make everything const by default unless stated otherwise.
Removing "const" just to satisfy compiler is called "cargo-cult programming". Don't ever do cargo-cult programming →
https://en.wikipedia.org/wiki/Cargo_cult_programming
I have already seen this talk on youtube. But it is good.
this was fantastic!
33:00 The real issue here isn't really due to this syntax quirk of C++ though. If you use braced initialization instead of parenthesized initialization (which you really should anyway), then a lock is taken as they intended... and then immediately released again in the same statement.
Edit: okay, he does eventually mention that too.
Loved the talk.
Great arguments for the rust programing language here.
If you need to be spoon-fed program flow in a multi-threaded environment, then yes, that's perfect for you. Enjoy your modern version of pascal.
"For my money I want better tools" me too, that's why I only use C++ as a last resort
0:56 Did he say "excetera" ?
No, thank you. I just stay with C.
Technically true but realisticly no. C++ were originally preprocessor hack on C that grown into it's own language with 99% backward capable with C.
That's what makes C++ attractive... the fact that it's more or less equivalent to a sort of preprocessor over C due to originally being this way, yes... It's what makes it easier to do low level integration (which makes using assembly for loops possible), and limits abstractions to the more concrete ones that are easier to understand and to debug since there's no variable typing or other special engines overlaid over the execution - a multiplication is a multiplication and not a "check type of A and B and cast if necessary then multiply and set type to 64bit float".
The C heritage is the reason why C++ is bad. I'd suggest Rust or Go instead for most applications where you would currently use C or C++.
Go has a garbage collector which is an instant disqualifier for my field. Rust might make sense though, I guess. (if you can link to it to/from C/C++ code and put it in a DLL).
Good luck with that. The modern world is banging on your door but you won't listen watching your black and white television.
Jules A - 2019-03-22
This talk is about some bugs in C++. Why are people bashing the language? Aren't there bugs in other languages too?