
Why should I have written ZeroMQ in C, not C++ - rumcajz
http://www.250bpm.com/blog:4
======
evincarofautumn
This is absurd. Exceptions are just generalised returns. You can use them well
and benefit from them, or use them poorly and make the stuff of nightmares.

It’s the same with any feature of any language. You can choose not to use
exceptions in your code, if that makes it easier for you to understand and
manage, but it’s certainly not the fault of the feature in general.

Basically, it’s up to you to structure your code well. Yes, it gets bad if a
potentially throwing function can be called from multiple points. The error
needs to be handled at every one of those points, and probably in much the
same way.

But if you see repetition, _why aren’t you factoring it?_ And why are you
calling that function from multiple unrelated locations in the first place?

I get it. I’ve used C++ for half a lifetime—it’s a hopelessly broken language.
There are tons of things about it that just make me furious. But I can get
stuff done in it because I’ve taken the time to understand it in depth. Don’t
complain about the language or a particular feature thereof just because it’s
not suited to your problem or your way of thinking.

There are other languages out there (Erlang) that are far better suited to
stable zero-downtime systems than C++. There are languages (Haskell, Lisp)
that help you better manage complexity than C++. Every language implementation
worth its salt has C bindings, so you can write performance-critical code at a
low level, while still managing the whole system in a high-level language.
There are options. Explore them!

~~~
mccoyst
One of his first examples is additionally absurd and is either the flimsiest
of strawmen or he simply doesn't understand when exceptions should be used:

    
    
        try {
            ...
            int rc = fx ();
            if (rc != 0)
                throw std::exception ("Error!");
            ...
        catch (std::exception &e) {
            handle_exception ();
        }
    

Why is he throwing exceptions and catching them within the same function? His
"C equivalent" is what he should've been doing in C++.

~~~
onli
He states how he understood exceptions:

"C++ exceptions just didn't fill the bill. They are great for guaranteeing
that program doesn't fail — just wrap the main function in try/catch block and
you can handle all the errors in a single place."

This is something i learned in my very first computer science lecture not to
do.

To be fair: It's what exceptions can be good for - a last barrier before a
crash and a way to handle errors later. But you're absolutely right that he
simply could react directly to the error. Or throw specific exceptions and
react to them. His described issue has nothing to do with exceptions
themselves, just with the way he thinks he has to use them.

~~~
cobrausn
Though we probably learned this is not the way to use them, I have seen
numerous real-world examples where this was the case.

Not only that, I don't think C++ exceptions are necessarily very good at being
a 'last barrier' before a crash - they simply can't catch all the errors,
because they are good at indicating conditions that might be recoverable, not
catching and recovering from logic errors that would cause a crash. There are
plenty of ways to hang yourself in C++ without ever throwing an exception.

~~~
figglesonrails
"Though we probably learned this is not the way to use them, I have seen
numerous real-world examples where this was the case."

Ah, Java code at my workplace.

    
    
       catch(Exception e) {}

~~~
LoneWolf
I believe you mean catch(Throwable t) {}

------
shin_lao
It looks mainly looks like a rant on exception, but nothing forces you to use
exceptions with C++. You can even allocate memory in a way that doesn't throw.

We don't use exceptions for the reasons described in the article (and many
others), we use boost::system::error_code instead.

But that's for the first half of the article, and the OP admits that he simply
gave up on exceptions.

As for the part about half-initialized state, I think the problem is that the
author is trying to do OOP in C++ without exceptions. Perhaps a more generic
programming approach would solve his "half initialized problem".

Don't want to sound like a snob, but it really looks more like a design
problem than a language problem.

~~~
vz0
I agree, this is just a rant on C++.

Coming from Java world, I can tell that it is nice being able to raise
exceptions from the constructor.

However, switching from C++ to C is absurd. C++ is (mostly) a super set of C.
Whatever you want to do in C, in C++ is also possible.

If there are some C++ features (exceptions, classes, contructors, etc.) that
are making his coding task more complicated, he should simply stop using those
features and refactor his code.

~~~
ufo
There is one advantage to writing in plain ANSI C and it is that you get it to
compile and run on _anything_.

------
pmjordan
This strikes me as throwing the baby out with the bathwater. While the
criticisms are valid, and people love to hate C++ for all sorts of reasons (I
avoid C++ exceptions altogether), C++ _is_ for practical purposes a superset
of C, so if a C idiom works better than its C++ equivalent, you can just use
it instead. I've been working on a project which has necessarily been written
mostly in pure C (kernel code), and I do really miss C++'s extra type safety.
(GCC has some type warnings that help, but it's still not as safe)

Then again, maybe an entirely different language, geared towards high
availability, such as Erlang or Ada, might have been a better choice in the
author's case.

~~~
cageface
The thing is, if you use the subset of C++ people usually recommend, you're
hardly better off than with C. Turning off exceptions means you can't use the
STL (alloc errors throw) and you can't do any non-trivial work in your
constructor so you have to manually initialize everything anyway.

~~~
scott_s
In C++, allocation errors don't need to throw an exception.

    
    
      Object* obj = new (nothrow) Object;
    

If the above allocation fails, obj will have the value NULL. It's tedious, but
you could replace the default, throwing allocation with a non-throwing
allocation in all places of the STL. However, various parts of the STL throw
other kinds of exceptions. But, I think one could have a compromise, where you
deal with exceptions from libraries you use, but you don't throw any yourself,
instead using C-style error handling.

~~~
cageface
If you replace the STL allocator with a non-throwing allocator how do you know
that that vector you just push_back'd didn't actually allocate any new memory?

~~~
james4k
Indeed, you have to roll your own data structures. This is pretty common in
the game development world, where exceptions are considered to have
unpredictable performance characteristics.

~~~
pestaa
That is a pretty tight requirement, considering the internals of Ogre 3D
engine. It is full with exception classes (some might argue it is way too
overengineered.)

Are custom data structures available as open source that don't use exceptions?
Or perhaps can you please name an engine that already has this?

~~~
james4k
There is EASTL, though I've never used it myself.
<https://github.com/paulhodge/EASTL>

Valve's Source SDK makes extensive use of their own data structures, however
it is very specialized. For example, linked lists are allocated as growing,
contiguous blocks of memory to reduce cache misses. The Doom3 source code
might be worth looking at, but I'm sure it's the same story.
<https://github.com/TTimo/doom3.gpl>

At the very least, there's a lot of great reference out there.

------
aidenn0
This describes quite well why I strongly recommend against exceptions in
embedded code.

There are ways that you can use constructors, one way is to have an error-code
as part of the object that the constructor can set. Another way is to use the
empty-constructor/init-method pattern that he talks about and wrap it in a
static method (or function) and that becomes your actual constructor. I
_think_ you can even make the constructor private which will prevent
accidental calling of it.

But this is just another example of why high-reliability systems require
considerably more discipline in C++ than in C, since C++ gives you more rope,
it's easier to hang yourself.

There is an argument that such a limited dialect of C++ is so close to C (with
a good 3rd party data-structures library) that there is no point to C++ in
such situations (which seems to be the point the article is making), and I
tend to go back and forth on this.

------
cageface
I really think the final nail in C++'s coffin is going to be its refusal to
play ball in a polygot world. Most languages let you drop down into C pretty
easily but C++'s weird name mangling, exceptions and complex, usually
nonstandard ABI makes interfacing with C++ a _major_ PITA. In the days when
C++ was used soup-to-nuts this wasn't such a big deal but these days you
almost always want some kind of higher level language on top.

Just look at all the contortions WinRT has to go through to expose its APIs
versus the clean Foundation/Cocoa layering you see in iOS/OS X for a great
example.

~~~
pjmlp
Name mangling is pretty common in any high level language, although people
only bash on C++.

~~~
wglb
Can you name some other examples?

~~~
pjmlp
Ada, Modula-2, Modula-3, Oberon, Haskell, ML...

I cannot give specific examples, but I am pretty sure that you'll have a hard
time trying to combine modules generated from different compiler vendors.

Already the first hurdle is that each vendor has its own language runtime that
is only compatible its own implementation.

Second, not all languages define a binary ABI on the language specification.

------
Locke1689
Going forward, I think C++ is not a bad choice, but I can definitely see the
distaste for exceptions. Unfortunately, as the author notes, simply not using
exceptions doesn't quite do it. Fortunately, the hard work has been done for
you. Much of Google's code was written in an exception-free manner before
newer evolutions of C++ came out. This means that they have banned use of
exceptions in their style guide. Luckily, it also means they've developed
workarounds for most of the exception pain points.

I would encourage everyone to take a look at the Google C++ style Guide[1].
Most of the complaints are addressed in that article. Constructors can only
signal errors through exceptions, so Google C++ allows only basic
initialization in the constructor -- all real work is done in an explicit
Init() method which can signal an error. I believe the guide addresses the
posters other concerns too.

In general, the Google C++ style guideline is a very good resource for writing
consistently good C++.

[1] [https://google-
styleguide.googlecode.com/svn/trunk/cppguide....](https://google-
styleguide.googlecode.com/svn/trunk/cppguide.xml)

~~~
drucken
Agreed, it is a very good guide.

However, the ZeroMQ author goes a lot further than that for his specific
application.

He made some reasonable arguments that even the use of OOP/classes in C++
makes catching undefined behaviour unnecessarily difficult for systems
programming.

~~~
Locke1689
His other objections didn't make a lot of sense to me. Destruction doesn't
seem like something that can fail. Your object has been deleted or it is going
out of scope. You don't even manually call the destructor. It should be about
freeing resources. what work is he doing in the destructor that can fail?

~~~
gchpaco
Well, fclose can fail, for example; it can as part of the closing process
flush its buffer and that can fail like any other I/O process. Further,
sometimes the error than happened during a previous write(2) call is only
detected in the close(2); think NFS and quotas, or check the man page. So
already we have errors that occur during teardown that need to be handled
somehow.

Similarly one can imagine using RIAA to hold a file lock, or a temporary
directory; this is a perfectly reasonable thing to do but there are dozens of
reasons why the final rm -rf of the tempdir could fail.

The idea that somehow object teardown is immune to failure is overly naive,
and the fact that you can't accommodate it easily in RIAA is quite
disappointing and makes the whole paradigm much less useful for carefully
coded software.

~~~
Locke1689
My claim is that object teardown is not what the destructor is for. Teardown
encompasses many things that are not resource releasing. Destructors are for
releasing resources, not necessarily guaranteeing their destruction.

For example, fclose can fail, but even if it does, the stream given is no
longer held. In fact, any further use of the stream is undefined. There is
certainly a place for logging in this situation, but if close was a _behavior_
of the class, it should have a separate close function.

As far as locking goes, it is the responsibility of the locking routine
(probably a semaphore) to release the callers hold on the lock, but it is not
the callers responsibility to ensure that whatever resources are associated
with the lock (e.g., a file) actually get deleted. That is the locking
object's responsibility.

I agree that some aspects of RAII could be better, but C is not the answer to
that. C doesn't even have scope-based RAII.

------
Meai
That's awesome, I'm already looking into crossroads-io. I like C because it's
that much more readable: There is no magic, you always know where things are
and where they are going, in terms of memory and control flow. C++ seems very
convenient at first, all the nice standard libraries do have attraction for me
but in the end you end up with tons of weird hierarchy magic, friend classes,
nested classes, copy constructors and destructors firing at the weirdest
places. Now everybody says: "Well you don't _have_ to use those!". Well, true
but in practice it doesn't turn out that way.

~~~
erichocean
If you're enough of an expert in C++ to use it in failproof ways, then you're
enough of an expert to do the same in C, and with far less mental overhead for
yourself and everyone who comes after you to read the code.

------
gruseom
90% of this thread isn't addressing his core point, which is that even if you
use C++ without exceptions, constructors and destructors still make it hard to
be strict about error handling, and the extra complexity isn't worth it for
projects like his.

Fine to disagree, but respond to the point. So far the relevant objections
I've seen are: (a) you shouldn't do anything in a constructor that might fail;
and (b) destructors can't fail. Weak. Is there a good counterargument? To be
precise: why is the OP wrong to say that, to be strict about error handling,
his C++ needs to look like the block of code that follows the sentence,
"There's a new 'semi-terminated' state" in the article?

(As for most of the comments, which boil down to "OP is ignorant of basic
things about C++ and programming", come on you guys, how likely is that? Who's
more likely displaying ignorance here?)

~~~
pestaa
Author went from constructors+exceptions to init_foobar()+return value for
error handling. When you misuse exceptions, they become unmanagable nightmare,
which I believe would have happened with 0MQ. And throwing exceptions in
constructors is one really good way to misuse them.

And ranting about it seems like ignorance to me, but that's beside the point.

For me, checking return values is just as, if not more, tedious than catching
some exceptions. Return values should be used to guide the flow of the program
state (IMHO), and exceptions represent invalid states.

~~~
gruseom
You still haven't responded to his point, which is that to deal with the
reality that constructors and destructors _can_ fail, he ended up having to
write more complex code than he would in C. (Specifically, the code in the
passage I cited, which turns each object into a little state machine.) Saying
"just make those things not fail" is no answer at all. So, to repeat: how
could he meet his error-handling goals in C++ without handling object
construction/destruction in that state machine style?

I have no opinion about this, but given that it's the point of the article,
that's what people should be addressing.

~~~
pestaa
It's not that constructors/destructors can fail, it's about the conscious
decision when you make them to. If you choose not to use exceptions at all,
you can prevent improper state before object construction, just like you would
in C's init_foobar().

------
crawshaw
For careful error handling, my favorite language is Go. It lacks exceptions,
so you have to return errors as in C. But it has python-style tuple return,
making it easy to return a value or an error from any function.

The fact that errors are explicitly returned requires the programmer to
explicitly handle them, which encourages design that considers error handling.

The evil of exceptions is they hide errors until they happen.

------
wladimir
Exceptions are indeed not the silver bullet to error handling. Handling errors
upstream can be useful as catch-all, but when the entire stack has been
unwound, it can be hard to recover the error usefully. Also it is hard to make
a sensible inheritance hierarchy, and every library chooses its own,
generating a forest of different-but-equivalent exceptions to handle.

A fully-fledged condition system (like Smalltalk, CL) would allow for a lot of
scenarios where exceptions currently give trouble. They would allow recovering
the problem where it happens, retrying operations, and so on. Too bad so few
languages have that.

However I don't think the right solution is to use an even more primitive
language. C seems simple, but you end up doing everything yourself that would
otherwise be done by the compiler, which is a lot more work, bug-prone, makes
the code verbose, and generally inconsistent (unless you're very disciplined;
forget about it in a team).

------
dustingetz
I wonder what error-monad looks like in C++, or C for that matter.

here's a rough, probably incorrect demo in python:
<https://gist.github.com/2653752>

gives you nice, clean, exception-like error handling that doesn't leak to the
wrong level of the call stack, and in a statically typed language the compiler
can verify your error handling for you. quite similar to checked exceptions.
call stack issues can be fixed with some low level C, or you could even unwind
the stack with some exception trickery.

------
Suncho
In C++, if you run into an error and you know how to handle it, you handle it.
This is exactly the same as C. Exceptions are only there for when you don't
know how to handle an error. Instead of calling exit(), you throw an exception
and hope that someone further up the stack can do something useful. By
default, your program terminates, just like exit... but all your destructors
get called, so you don't leak database handles or locks or other resources.
Nice.

I've read the Google C++ style guide and it's basically a joke. At least it
was a joke two years ago. The guide even contradicted itself in multiple
places. Google bends over backwards to avoid using exceptions and the result
is that C++ isn't C++ anymore.

~~~
alpatters
I agree with this entirely. Exceptions and errors aren't necessarily the same,
i.e. errors aren't always exceptional cases. When errors can be dealt with
locally they should be. The problem comes when an error can't be dealt with
locally. Then as stated, exceptions can be used to propagate the condition
upwards in the stack where some other component may be able to deal with it.

------
haberman
I struggled with a similar question for my low-level protobuf library UPB
(<https://github.com/haberman/upb>). Here are some blog posts describing my
dilemma about this: <http://blog.reverberate.org/2009/11/porting-upb-
to-c.html> [http://blog.reverberate.org/2009/12/torn-over-c-
question.htm...](http://blog.reverberate.org/2009/12/torn-over-c-
question.html) I ultimately chose to stick with C, and I'm happy with my
decision.

When people ask me why I stuck with C, it's difficult to give a single
overwhelming reason why C is better. The most clear-cut one is that C++ is not
supported in the Linux kernel and I want my library to be usable there. But
the other reasons why I prefer C are not as easy to quantify.

One reason is that code written in C is more transparent. You can look at some
C and know what it is going to do (add some numbers, call a function, etc).
Macros are the one exception to this, but good C programs use these sparingly
and clearly mark the macro with an UPPER_CASE_IDENTIFIER. C++ is much harder
to "see through." Any function call could end up throwing an exception which
does a non-local exit from the function. Any addition, assignment, pointer
dereference, etc could actually be an overloaded operator. Any function call
could be performing a user-defined implicit conversion on any of its
parameters. For overloaded functions, the compiler decides what function is
actually called by applying non-trivial pattern matching rules. The runtime
will automatically invoke any static initialization code (like constructors of
global statics) pre-main in an undefined order. etc. etc.

I intend to get a thorough security review of my library once its design
stabilizes. I asked Tavis Ormandy (a fellow Googler and security badass) which
language is easier to audit for security and he said C for the reasons of
transparency I listed above.

People often say that you can just avoid using the parts of C++ that you don't
like. That is true, but hard to enforce, especially on a multi-person project.
If you're asking others to follow your set of rules, you have to write those
rules down in meticulous detail, leading to something like the Google C++
style guide ([http://google-
styleguide.googlecode.com/svn/trunk/cppguide.x...](http://google-
styleguide.googlecode.com/svn/trunk/cppguide.xml)), and at that point you're
asking your contributors to study and internalize a large and complicated list
of what is and isn't allowed just for the privilege of contributing to your
project. I don't think this approach scales to lots of projects that are all
choosing a different subset of C++.

There are definitely things I miss by not having C++'s facilities.
Constructors and an implicit "this" parameter are both really nice.
Constructors are remarkable in that you can write a single function that gives
you three different construction patterns for free (direct construction, heap
construction with "new", construction in an arbitrary location with placement
new). Automatic upcasts are nice and totally safe. Inheritance and
public/private specifiers let you express directly lots of things you can only
express with comments in C.

But overall I think that using straight C is the right choice for a project
like my library UPB.

~~~
aerique
C is superior for libraries since a lib can then be used from so many other
languages. A C++ library that doesn't provide a C API is an absolute nightmare
to write bindings for.

~~~
cbsmith
So true. Binding to Python is such a pain:
<http://www.boost.org/doc/libs/1_49_0/libs/python/doc/>. Lua is even worse:
<http://www.rasterbar.com/products/luabind.html...>.

Seriously, once you know how to use it, C++ actually makes binding to a lot of
higher level languages a lot nicer than doing so with C.

~~~
p_l
... I am sorry, but that's _very_ untrue.

As it happens, not every language is implemented using runtime written in
C/C++, nor does every language modules written in C/C++ to extend it instead
of FFI.

Dealing with libraries written in C++ without C API is one of the worst PITAs
in my experience, leading to crazy things like KDE's SMOKE (which, to make it
funnier, has bad documentation, so I'm still unsure if I can make it work
outside Qt's object model)

~~~
cbsmith
> ... I am sorry, but that's very untrue. > > As it happens, not every
> language is implemented using runtime written in C/C++, nor does every
> language modules written in C/C++ to extend it instead of FFI.

You did an awesome job tearing apart that strawman, but you are
misrepresenting what I said. That second sentence is in no way in conflict
with my " _very_ untrue" statement.

To refresh, with emphasis added for the reading impaired:

    
    
        C++ actually makes binding to *a lot* of higher level languages a lot nicer than doing so with C.
    

That you can find a distinct subclass of languages where you believe that it
is hard to do bindings to C++, doesn't mean the above statement is even mildly
untrue, let alone very untrue. Please review and reconsider:

* There are certainly a lot of higher level languages which don't qualify for your definition. * SMOKE is actually a binding through Qt's MOC, which is generally considered by the C++ community to be something which makes Qt pretty un-C++-ish. You are right to phrase it as "Qt's object model", because it sure as heck isn't C++'s.

Try looking at the LuaBind and Boost.Python libraries. They represent a very
different approach to language binding, and it isn't dependent on there being
a wrapper C API. While writing binding framework for a given language is a bit
of a PITA, once that has been built, it really does make binding to a high
level language a lot easier than trying to do it through a wrapper C API.

------
vz0
GCC is finally switching from C to C++, and they are actually avoiding
exceptions and RTTI.

<http://gcc.gnu.org/wiki/CppConventions>

I salute them on following strict coding conventions.

------
pkmays
I'm not C++ savvy, but I know from reading Google's C++ style guide that they
also disable exceptions. The guide leaves it at that and doesn't say anything
more about how to deal with errors. Does anyone here know how these big Google
C++ codebases handle errors instead?

~~~
andyjohnson0
[The following is speculation: I have no access to Google's code.]

I can't think of any other way to handle errors apart from using return
values. Methods return error codes which are handled by the caller or bubbled-
up to its caller. This tends to result in lots of duplicated error handling
code, and you have to either dedicate the return value to success/fail (which
means you have to return non-status data some other way) or use special values
to indicate failure.

The Go language (from Google) doesn't have exceptions and allows functions to
return a value and an additional error return value [1]. I'd guess that this
is inspired by their approach to C++ coding.

[1] <http://code.google.com/p/go-wiki/wiki/Errors>

~~~
rb12345
Isn't it possible to fake this with C++ templates? As an example, I created
<https://github.com/rb12345/cpp_annotated_return>, which uses a templated
struct to allow multiple value returns.

~~~
andyjohnson0
Yes, you could do it that way. Personally I'd restrict the error code to
always be an int, which makes for a terser syntax as you don't need the second
template parameter.

You could also extend it to support multiple non-error return values, like
Python does. But this introduces problems with expressing the contract between
caller and called (e.g. [1]) and I think the best way to address this might be
to extend the language syntax.

I think one of the most interesting design choices in Go is that it
intentionally omits _conventional_ exceptions. It does have
defer/panic/recover [2] though.

[1] [http://stackoverflow.com/questions/354883/how-do-you-
return-...](http://stackoverflow.com/questions/354883/how-do-you-return-
multiple-values-in-python) [2] <http://blog.golang.org/2010/08/defer-panic-
and-recover.html>

------
RandallBrown
This may just be because of when I learned to program, but I find that writing
object oriented code makes everything easier to understand. The stuff you need
to do with C where you're passing around structs and state and pointers
usually looks pretty ugly to me.

Error handling is a pain in any language. "This thing that should NEVER fail
just failed, now what?" If you're not in a recoverable state, realistically,
what can you do?

I know that constructors _can_ fail, but it's pretty abnormal for that to
happen. I like the way objective-c handles it. Since everything is dynamically
allocated and you can just see if the object exists to find out if it works.
Lots of methods have an extra NSError parameter that you can use if you need
more information.

------
zvrba
His reasoning is bogus. For his C equivalent, he writes:

> There are only two states. Not initialised object/memory where all the bets
> are off and the structure can contain random data.

He can get exactly the same effect by mimicking fstream interface: use
constructors and destructors as they were meant to and introduce bool
operator! to check whether the object has been successfully initialized.

In this scenario, only destructor needs to know about the "fail-constructed"
state. Other methods don't need to implement the state-machine; calling them
on "fail-constructed" object would be undefined, _exactly as in his C version_
(e.g., calling foo_bar without calling foo_init and checking that it
succeeded)!

------
jacquesm
The one advantage of C over C++ is simple: what you see is what you get.

If you have to wonder about what a statement really might mean depending on a
bunch of state that was fed to the compiler then that really spoils things.

------
malkia
Just to quickly note here: Certain very popular game console does not allow
use of C++ exceptions - the underlying runtime / abi / whatever simply does
not support it.

Not that you would ship ZeroMQ code in it (it's GPL), but still.

Oh, and I love ZeroMQ, and I even love it more, that the "C" interface was the
one being public, not the "C++".

Also good article. I love exceptions in higher-level languages - lisp, lua,
etc. - but I prefer error codes in lower-level ones, and I consider C++ as
such.

------
ltratt
I agree fully with the author - exceptions are a problem for software that
wants to avoid unexpected behaviour. I noted something similar in
[http://tratt.net/laurie/tech_articles/articles/a_proposal_fo...](http://tratt.net/laurie/tech_articles/articles/a_proposal_for_error_handling)
and sketched a possible compromise, more to emphasise the point, than as a
serious proposal.

------
st3fan
Interesting read but the problem is not C++ here. The problem is the author's
usage of C++ and specifically exceptions. If he does not like exceptions then
just implement more traditional error handling while keeping all the other
good things that C++ provides.

------
signa11
>Now consider what happens when you add inheritance to the mix. C++ allows to
initialise base classes as a part of >derived class' constructor. Throwing an
exception will destruct the parts of the object that were already successfully
initialized with this

which object is he talking about here ? if foo inherits from bar, object foo
is not considered a _valid_ object till it's constructor _completes_. so there
is no question of destroying parts of objects which were already constructed.

similarly, during object destruction, as soon as the destructor is invoked,
the object is in an invalid state.

i guess there are some issues in understanding of object lifetimes and
exceptions thrown by it's constructors...

------
HardyLeung
The reasoning is very poor. I thought he was going to say something along the
line of portability. Nope. It was about exception.

Granted, exception is problematic. I don't use exception for similar reasons.
However, given the nature of this project, it should have been clear that
exception should not have been used in the first place. Instead, be very
explicit about error handling. This is really a poor design choice. How is it
the conclusion that the answer is C, rather than "C++ without exception?".

------
cpeterso
C++ exception specifications are worse than nothing. Unlike Java's
(controversial) checked exceptions, C++ exception specifications are not
compile-time checked. Instead, the compiler generates run-time checks when
calling function functions with exception specifications. If the function
throws an exception that does match its specification, the program calls
abort()!

------
ynniv
As with most experiments in writing object oriented code in C, this looks a
lot like Objective-C.

------
ecopoesis
Exceptions shouldn't be used as gotos. Instead of letting every exception
bubble to the top, handle them at the appropriate level in the stack where you
can recover from the error they representing.

------
JohnnyContra
Bjarne did it all for us.
<http://harmful.cat-v.org/software/c++/I_did_it_for_you_all>

~~~
no_more_death
A spoiler: <http://www.snopes.com/computer/program/stroustrup.asp>

------
12uu45dd
Oh well. It was probably faster and easier to code in C++ initially. And
allowed him to beat all the competition to market.

------
vph
looking forward to crossroad i/o. This step will drive the two projects even
further apart. But zeroMQ is already established, and its name is more catchy.
Good luck.

------
nirvana
_"First, it's important to take into account that ZeroMQ was intended to be a
piece of infrastructure with continuous uptime. If should never fail and never
exhibit undefined behavior."_

There is one language/platform[1] I'm aware of designed for this type of
system, and which achieves it beyond all others: erlang.

If Uptime is important, how do you handle it when you want to update your
software under C++ or C? You have to bring the service down. Erlang supports
updating software while its still running.

If exception handling is important (to prevent crashes) how do you handle it
when there is a bug? Erlang has supervisors that not only help you manage
exceptions but keeps the service going when an unhanded exception causes
things to crash.

More importantly, intrinsic to the nature of the way you write erlang code,
you eliminate a great deal of the possible errors. In C code you have to check
to make sure things are in the right state while running your code. In erlang,
your code doesn't run (the function isn't called) if the state isn't right to
handle it. It flips this problem eliminating many classes of errors. Further
there is OTP support for many types of processing (like state machines) that
makes writing these types of solutions much easier.

Erlang is great for making sure no undefined behavior happens. Erlang is also
great (as I understand it, this I haven't gotten into) for creating unit tests
that can fully exercise the code across all possibilities.

Where does erlang suck? I don't think it sucks anywhere because it has
solutions for all of its own problems. For instance, single node performance
of an erlang program (which runs in the BEAM VM) is going to be lower than
single node performance of a C program... but in erlang you can increase
capacity nearly linearly simply by adding more nodes... while this is nearly
impossible with almost all C/C++ programs without spending a lot of time
working on it.

But where erlang _is_ weak is that single node performance which might be
really important[2], and if it is, you _can then write your performance
critical bits in C_.

Thus the things that do the real work can be fast and in C but the things that
keep the system going and distributed (where performance of this kind is much
less critical, but performance of the operational kind is paramount) can be
written in erlang.

So, I think the second mistake he made, and is still making, is thinking that
the project has to be written in a single language.

If you use the best language for the job, then sometimes that should mean
using two languages right?

Erlang is not a hipster language. No hipsters use erlang. It is 25 years old
and boring and %99.9999999 uptime. Its ugly. Its not hot and fresh and new.
But it is the right language for the job, when you've got a system that need
to run across cores or nodes, or have very high uptime.

And really, it doesn't take but a couple weeks of learning. Then the syntax
will be gorgeous and you'll be a better programmer for it.

[1] I say "I'm aware of" for a reason. There may be others as well suited when
this is the primary goal, possibly even better suited. I don't know all
languages. But I do have a pretty good survey started in the days when new
languages were as common as YC batches and much more experimental than they
are now. My point isn't to bash other languages but to promote one that isn't
understood correctly by many people.

[2] I think this is the case a lot less often than people think. People
benchmark things on a single node even when they know they are going to build
a cluster of machines to run them, and then pick them based on this. Redis is
really fast. Is redis distributed? Riak has a fully distributed in memory
database (which means 10 32GB nodes means you can store 320GB in RAM if you
want, rather than have 10 nodes all storing the same data in a cache, and thus
much less data cached for the same number of machine with something like
Redis.

~~~
rumcajz
The article is about undefined behaviour. Erlang won't help much with that.

~~~
viraptor
Depends how you write your code. Actually Erlang is pretty good at avoiding
undefined states (which can be thought of as undefined behaviour) by putting
everything in an OTP framework. There's no custom "I'll just handle this
earlier here in a tricky way" - if you stick to OTP you'll have message
handlers and state machines. That's really awesome if you're programming
network daemons. You can pretty much follow the state machine diagram and make
sure that unless some progression is possible, it will not occur in practice.

Testing based on OTP service trees also makes the verification fit the
possible transitions in a much closer way than trying to cover all the
branches in an OO app.

So yes, I'd say it's actually quite a good response to an "exception handling
all over the place" problem. You simply don't do that. Instead your exceptions
finish at the FSM level and progress you to one of the error states on your
diagram. You know exactly what state you're in at that point so the behaviour
is pretty well defined at almost every step.

However zeromq is a library that was supposed to be portable, rather than a
daemon itself, so from that perspective, it's a very bad fit for ZMQ.

~~~
regularfry
What worried me about Erlang was that when a process dies and gets restarted,
the message queue for the old process gets thrown away. Neither the sender(s)
nor the new process can tell how many messages were lost.

~~~
viraptor
If you care about reliability of the delivery, you can do a number of things:
do a single call, wait for response and retry if needed, or store the messages
in mnesia and only notify there's something to pick up (pull scenario with
ack), or do a number of other possible things.

Lost messages are a fact of life really - the same will happen with any other
system - either you persist the message and ack the reception on every stage
or you risk dropping the queue.

------
xxiao
on the exception handler part, i don't think you're forced to use c++'s try-
throw-catch, you can still safely use the C-style exception methods, after
all, c can be used as a subset of c++, though not 100% of the time.

------
pwpwp
wat?

------
latch
The background made that post unreadable for me. Minimalism done wrong.

~~~
dgritsko
Try readability.com.

~~~
parfe
Even easier in Firefox: View -> Page Style -> No Style

