
The Dark Side of C++ (2007) [pdf] - glazskunrukitis
http://www.fefe.de/c++/c%2b%2b-talk.pdf
======
Glowbox
This presentation is from 2007. It's outdated and full of errors. I'll refer
to the comments at /r/programming
[http://www.reddit.com/r/programming/comments/193o4p/the_dark...](http://www.reddit.com/r/programming/comments/193o4p/the_dark_side_of_c_pdf_you_lucky_firefox_19_users/)

~~~
alexchamberlain
I call BS on most of the presentation. For example, throwing exceptions from a
constructor is not only acceptable, it's the only way to prevent construction.

~~~
epidemian
Exactly. One valid criticism could be that getting exceptions right in C++ can
be quite a challenge; i remember that at one point i was very into the
language and was blown away by reading Exceptional C++ ( _really_ recommended
for any C++ programmer), i was like re-discovering the whole language
altogether.

~~~
nikic
Most people just miss the common C++ idioms that solve many of the exception
issues in very elegant ways (and give a lot of benefits at the same time).

E.g. the example with file open + close in the presentation is laughable.
Every C++ programmer knows that this is something that should be done with
RAII. I.e. instead of manual close calls you let the destructor handle it.
This is both exception-safe and spares you remembering to add a close call on
every possible exit-path.

Also one should point out that C++11 has unique_ptr and shared_ptr which in
many cases remove the need for the programmer to manage things by himself.

~~~
betterunix
"I.e. instead of manual close calls you let the destructor handle it. This is
both exception-safe and spares you remembering to add a close call on every
possible exit-path."

Unless closing the handle causes an exception to be thrown. Either you never
see the exception or your program aborts, and neither one is particularly good
if you want to write reliable code.

~~~
ycombobreaker
"Unless closing the handle causes an exception to be thrown."

That is a straw-man argument. If the underlying file-closing API can throw
exceptions, they must be caught from the destructor. If that means that they
get ignored, then that is what it will have to be (much the same as most C
programs ignore the return call from `printf`). Also in this case, the RAII
wrapper should provide a member function which can execute the underlying
close call early and expose the failure, for users who may be interested in
guaranteed reliability.

In any case, provide RAII _safety_ does not intrinsically reduce reliability.
If your destructor is executing code which _must_ succeed or be handled at a
higher level, then a good developer will not put it in the destructor. No
language feature can solve the question of "where should the program stop
caring about failure?"

~~~
cliffbean
> in this case, the RAII wrapper should provide a member function which can
> execute the underlying close call early and expose the failure, for users
> who may be interested in guaranteed reliability.

Indeed; this is a useful technique. However, it means that you now have a
close() method which you have to call on every exit path, because if you miss
a path, that's a path which could have an exception thrown from a destructor.
And that basically means you're not doing RAII anymore.

So yes, RAII is intrinsically incompatible with this kind of reliability.

~~~
ycombobreaker
> However, it means that you now have a close() method which you have to call
> on every exit path, because if you miss a path, that's a path which could
> have an exception thrown from a destructor.

Not true at all. `close` and the destructor should be idempotent. In the main
path, `close` will get called and failure will propogate upward. In any other
failure path, the destructor will attempt to perform the underlying close and
allow the stack to unwind without any further interruption.

Of course, anyone can come up with pathological cases where this is not
acceptable behavior from a high-reliability sub-component. And in such a
situation, RAII may not be the best answer (nor would lexical scoping i.e.
constructor/destructor, for that matter!) But in my experience, this approach
is just fine for most application-level code.

~~~
betterunix
...or we could retool exceptions so that destructor exceptions are safe (as
long as they are caught). Conditions in Common Lisp, for example:

[http://www.gigamonkeys.com/book/beyond-exception-handling-
co...](http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-
and-restarts.html)

------
mrich
While some points may be incorrect and some outdated in this 2007 presentation
there are valid points. Especially it is true that the behavior of a line of
code in C++ cannot easily be inferred from it alone, which can quickly become
a problem as a code base grows in size and there is no common coding standard.
A coding standard and automatic tools to enforce it (think clang-based
compiler plugins that run before commit) can solve such problems and make C++
still one the best languages out there for high-performance programs, while
guaranteeing good maintainability of the code.

There is C++ code out there which reads beautifully and is correct, you just
have to work a little harder than in other languages. When you need the
performance and control then it is worth the additional effort.

~~~
JoeAltmaier
To be fair, template error messages are still a black art. They can take half
a page. Reminds me of the old CFront days when C++ compiler was a front-end
for another compiler. Templates are not very well integrated still.

~~~
mrich
clang has solved this problem mostly with their template type diffing. gcc has
also improved in that area.

<http://clang.llvm.org/diagnostics.html>

~~~
JoeAltmaier
Cool, but the template examples leave me unconvinced. When I get to work, I'll
paste in an epic template error; hard to see how clang could make it all
better :)

------
karterk
Hmm, I found some of the criticism unfair. E.g. the example with "baz =
foo->bar(3);". Yes, "bar" could be a number of things here, but that's why
variable naming conventions help.

The point about operator overloading is accepted, but this is not too
different from what happens with metaprogramming in Ruby or say macros in
lisp.

Even python has some quirks. See:
[http://stackoverflow.com/questions/1132941/least-
astonishmen...](http://stackoverflow.com/questions/1132941/least-astonishment-
in-python-the-mutable-default-argument)

~~~
jrajav
> Hmm, I found some of the criticism unfair. E.g. the example with "baz =
> foo->bar(3);". Yes, "bar" could be a number of things here, but that's why
> variable naming conventions help.

Then why must variables have static types?

~~~
AnthonyMouse
What does one thing have to do with the other? Static typing reduces runtime
errors by requiring you to be explicit when you want a nontrivial type
conversion. There are entire classes of errors and security vulnerabilities
that come from poor type checking. SQL injection is purely a result of SQL not
requiring type information, which causes the SQL server to be unable to
properly distinguish between the end of user-provided data and the start of
the next statement, foisting that task onto the programmer who neglects it at
his peril.

------
npsimons
Some valid points, but I was hoping for more meat, maybe references to what I
call "dark corners" of C++. Take, for instance, writing a simple logging class
that can log to multiple places and can be used in place of std::cout. The
solution I initially came up with is a variation on
<http://wordaligned.org/articles/cpp-streambufs>, with some manipulator magic
thrown in to adjust severity level. Ah, but that's not good enough, you have
to pull some interesting gymnastics to ensure order of IOStream
initialization: <http://accu.org/index.php/journals/264>. And after all that,
I'm still not sure it works, as looking at the data structures in a debugger
looks like garbage (guess why I'm in the debugger in the first place).

All that being said, I still love C++. I'm glad I know it as well as I do so
that I can (usually) avoid problems, but even then I run into compiler (or
build!) dependent problems that shouldn't be happening. C++ has problems, and
we need to address them. I'm happy to say that even though I am stuck with old
compilers that have inscrutable template error messages, time moves on and I
am aware of this problem being fixed in newer versions of compilers.

------
tawgx
C++ is a really tough language, especially when compared to more modern ones
(Python, Ruby, Scala,..). There are two things which I've always found
frustrating about the language. The first is that there are so many arcane
elements to it that even highly experienced devs can make mem alloc mistakes
that will cause the app to SIGSEGV down the road, and it's pure misery to root
these out. The 2nd has to do with that it's not really cross platform in that
it can be super hard to move code between win and nix, something that
languages like Java and Python have all but made transparent. I know there's a
lot of work done on C++ the last few years, but nowadays while we still write
C++ for some parts of our app there's almost always a legacy part to it.

------
Devid2013
Another bad article against C++. There is no perfect language and C++ is not
perfect too. But using some other langauges I fell offten like be prisoner...

~~~
zanny
I was exploring some features of Android this week and every other line I kept
sticking comments in like "gosh, if only java had first class functions /
closures / operator overloading / namespaces / global primitives that aren't
hackneyed"

------
gtani
Haven't had one of these anti-C++ threads/rants in a while, prbably not much
new here

<https://news.ycombinator.com/item?id=4969372>

<http://news.ycombinator.com/item?id=4539251>

<http://news.ycombinator.com/item?id=3712292>

______________

this mechanization of the lang spec in Coq looks interestng

<http://hal.inria.fr/hal-00674663/en>

------
gcv
Some valid points, some outdated ones. I have found C++11 surprisingly
enjoyable. Real lambdas, templates, and unique_ptr/shared_ptr have let me
write exceedingly Lispy and highly-readable code. With great performance
characteristics.

Minimizing the use of OOP helps avoid the language's sharp corners. With
C++11, I highly recommend abandoning the "C with classes" style.

------
72deluxe
Ugh. These C++ bashing articles, although being highly popular, are extremely
grating. All languages have issues. The End.

~~~
slurgfest
Different languages have different kinds of issues, and these have different
levels of importance for different projects and audiences.

------
cwgem
I checked over the reddit thread mentioned in one of the comments, and a few
of the comments here, and notice people mentioning how outdated the
information is.

Out of intellectual curiosity, what resources (books, sites, etc.) would be
recommended for modern, best practices C++?

------
tehwalrus
I literally didn't know that vector<T>::operator[] doesn't do index checking
for me. I've written some C++ code in Python extensions where I use vector<T>
to simplify from (T* arg, int arg_length) which I now find out could randomly
segfault.

Blergh. This stuff is why I use Python (with snippets of C for speed): when I
do something stupid, I get an error message and line numbers, not a faceless
segfault (+even when I get a C segfault, I can still get the python stack back
with faulthandler..)

------
chrisbennet
This a download link for a PDF. Please either don't do this or note it in the
title. Not everyone wants to download a PDF to their mobile device.

~~~
glazskunrukitis
Updated the title. Sorry for the inconvenience.

------
dtld
C++ is complicated before you know more about it.

------
simfoo
The author also runs a blog written in C (blog.fefe.de)

~~~
allerratio
And written an own Libc: <http://www.fefe.de/dietlibc/>

------
tezka
full of crap. It sounds like when an office clerk in a publisher house demands
abandoning latin words, puns, ironies figures of speech etc. because he is too
dumb to use them properly. There are poets and there are mba-style bullshit
writers. Great C++ code can read as beautifully as poems in style and elegance
(c.f. Elements of Programming by Stepanov).

~~~
edgls
Well, the compiler error messages (few examples given by the author of the
article) also looks like poetic phrases to you :D

------
jejones3141
"There is no dark side of the moon really. Matter of fact it's all dark."

------
dtld
Is there an article named The Dark side of mathematics?

------
DanBC
meta: how come this didm't get scribd'd?

~~~
ordinary
My bet would be that it's because the URL doesn't end in '.pdf'.

------
pertinhower
Man, never noticed how the quality of front-page HN posts on a Sunday morning
really bottoms out.

------
itistoday2
That's just ridiculous. C++ has no light side.

------
dakimov
I agree. C++ is a poorly designed language with a lot of "bugs" in it.

Languages do not pass the usual development cycle that includes collection of
requirements, beta-testing and bug fixing. C++ have some obviously stupid
design decisions that apparently will never be fixed.

Strangely or not, people tend to approach languages religiously rather than
rationally.

Languages are like holy scripts that are written by one or a few people that
are perceived like gods, and there is no proper critism or improvement
following the development of a language.

Hence what we have today.

One of the most popular languages is full of stupid design mistakes that will
never be fixed, they rather die with the language.

Actually, an example of a language that fixes many of the C++ problems is C#.
But it inherently cannot be a replacement of C++.

Again, people are not rationally thinking creatures.

And to all who are not rationally thinking, I just say: fuck you.

~~~
mrich
You cannot determine the "best language" (for a given project) from a computer
science aspect only. In the real world things like availability of
programmers, existing code/interfacing with libraries, support of different
platforms etc. play a much larger role.

D may be superior to C++, but if you have to build a firmware in one year and
you will need 20 developers you cannot use this language since you cannot hire
that many experienced developers and the D compiler may not even target your
platform.

Even luck and being in the right spot at the right time by coincidence play a
large part. Consider Javascript, which was never designed to do all the stuff
people use it for nowadays. But for all its flaws it solved people's problems
at the right time and therefore got popular. It was the same with C and C++.

------
rspring
Yea, let's write all of our higher level object juggling in C++! Such a nice
language, isn't it? And there aren't much alternatives either, right? Let's be
honest: if you find yourself complaining about C++ syntax and error messages
while coding your higher level logic, chances are you either like the pain or
you have lived under a rock for the last 15 years. In the latter case, go open
your browser and type "Python" (or "JNI" or "Javascript" for that matter).

~~~
tapatio
Yeah, because you can write hard real time code in Python or JavaScript.

~~~
tapatio
Better stated, there are applications where you can't use JavaScript or Python
due to timing requirements - software defined radios for instance.

~~~
rspring
I agree. And that's exactly why there exist interface languages such as JNI so
you can write your higher level code in a nice language and get down to C/C++
for the time-critical parts. I don't see much of a problem here.

~~~
blt
This introduces a whole new category of pains in the ass. You need to run two
debuggers at the same time. Inverting control with callback interfaces is
tricky. there can be friction between the memory ownership models in the
managed and native code. And it just makes the system that much more complex.
I've been working in a python / c++ interop system for a while and I think
some of the c++11 features make the benefits pretty questionable.

