Live data from Hacker News

Why should I have written ZeroMQ in C, not C++ (2012)

250bpm.com

141–150 of 170 posts

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#141
post #22

1. That "C equivalent" for error handling is not an equivalent at all. If one could handle the error in the same function then there is no reason to throw. The "C equivalent" is returning an error code, which has other problems. 2. One can handle errors in initialization without exceptions and half-initialized objects: Make your constructor private and expose a static member function that returns an optional (where T…

[deleted]

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#142

Earlier quoted context omitted.

Would you say either is something you would put in a decently scaled production system?

Using ZMQ (from C) at high volume, we found it dropped data, so we abandoned it.

What did you replace it with?

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#143
post #13

I was trying to figure out if this was satire. C++ gives you strictly more tools, particularly for guaranteeing reliability, and they're all optional. What particularly laughable here is the split ctor/init pattern is allegedly driving them towards C, whereas C doesn't even give you dtors! If you're forgetting your init calls, are you really telling me you're not going to forget your destructor call? There are plenty…

> C++ gives you strictly more tools, particularly for guaranteeing reliability, and they're all optional. You are right. But it doesn't help. When I used C++, I constantly shot myself in the foot by using its features. It did not feel like overusing, but I just wanted type-safety and to replace macros. It was impossible to restrict to useful features, because they are all useful in their way, only they come at the pr…

> You are right. But it doesn't help. When I used C++, I constantly shot myself in the foot by using its features.[...] I went back to C. It's a relief.

I'm sorry but I really can't stand this mindset.

For me it is like to say "I got a car, but driving fast was so dangerous...I got scares and I stayed pedestrian for the rest of my life. It's a relief."

No it's not a relief, it's non sense. It's not because my car goes to 200km/h that I have to do it. Same for C++ usage.

Just learn which features you need instead of throwing the baby out with the bathwater

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#144
post #130

Earlier quoted context omitted.

That exact same problem exists in C in the exact same way. It's somewhat less of an issue just because C is essentially frozen in time, but it has the same inherent problems & design issues. But if you statically link your C++ runtime & only expose C interfaces then you're fine. You can be "just like C" only at the ABI boundary, that's well supported and works great. It's a quite common setup even. Like for your part…

"But if you statically link your C++ runtime" - you need to take careful measures your symbols not to leak as visible. Doable, but takes some time. Also might be easier with gcc/clang - e.g. -fvisibility=hidden, but nothing like this in msvc AFAIK.

Msvc symbols aee hidden by default, but why would symbols be visible be a problem ?

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#145
post #44

By now he probably realizes that the Java version is what he was looking for all along: https://github.com/zeromq/jeromq Why C/C++ coders don't even write "Hello World" in Java SE before drifting away into rewriting the ball bearing (1907) part of the wheel is beyond me. The Throwable class is exceptional in every way, it wastes almost nothing and gives the programmer the ability to catch all problems that occur in t…

> Why C/C++ coders don't even write "Hello World" in Java SE before drifting away into rewriting the ball bearing (1907) part of the wheel is beyond me. I write C++ & Java on a daily basis. I don't know why I would ever willingly choose Java for a personal project. It's not fun & it's inflexible. And the C++ side of me cringes with how inefficient & slow "simple" things are. Especially for anything that doesn't last…

I find Java a lot more fun if you don't use getters/setters for everything.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#146
post #130

Earlier quoted context omitted.

"But if you statically link your C++ runtime" - you need to take careful measures your symbols not to leak as visible. Doable, but takes some time. Also might be easier with gcc/clang - e.g. -fvisibility=hidden, but nothing like this in msvc AFAIK.

Msvc symbols aee hidden by default, but why would symbols be visible be a problem ?

That's not true at all. Sorry they are completely visible, unless all of them are "static". Most of all it also leaks what imports need to be done - as in I require this from MSVCP140.dll or MSVCP140_1.dll - like "_CxxFrameHandler4"

Again I'm talking about statically linked libraries, linked to the dynamic CRT (MSVCRT - e.g. /MD, not /MT)

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#147
This is a complete straw man argument against C++ based on exceptions vs return codes. C++ can handle C return codes, and the compiler comment needs some data to back it up. I would give this more than a grain of salt if the author had an 'alternatives considered' section or some other legitimate arguments like "I'm OCD and I just can't handle the fact that if I want to alphabetize the methods in the declaration for a base class it's a breaking change in terms of binary compatibility for a shared library."

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#148

Earlier quoted context omitted.

In Rust, this destructor is perfectly fine: impl Drop for Foo { fn drop(..) { self.cleanup(); self.free_memory(); } } even if `self.cleanup()` panics. When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. If there is a `catch_unwind` somewhere, these leaks will grow over time. The same code in C++: ~foo() { this->cleanup(); this->free_m…

> In Rust, this destructor is perfectly fine: Sort of; it's very rare. You don't really write free_memory, unless you're doing some very specific unsafe things. > When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. It will be leaked if panic=unwind and if you use catch_panic. catch_panic is not used very much. Partially because panic=…

> It will be leaked if panic=unwind and if you use catch_panic.

This isn't fully accurate. It is leaked if you use `panic=unwind` and the panic unwinds the function. At that point, the program is still running, but the memory is unreachable through a pointer in the program, and therefore leaked.

Whether you actually catch the panic afterwards doesn't matter. Not catching it will terminate the program, but then the program will be terminated with "leaked" memory, and tools like valgrind will report it as such.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#149

Earlier quoted context omitted.

In Rust, this destructor is perfectly fine: impl Drop for Foo { fn drop(..) { self.cleanup(); self.free_memory(); } } even if `self.cleanup()` panics. When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. If there is a `catch_unwind` somewhere, these leaks will grow over time. The same code in C++: ~foo() { this->cleanup(); this->free_m…

> In Rust, this destructor is perfectly fine: Sort of; it's very rare. You don't really write free_memory, unless you're doing some very specific unsafe things. > When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. It will be leaked if panic=unwind and if you use catch_panic. catch_panic is not used very much. Partially because panic=…

> Fallability in Rust is spelled "Result", and drop does not return one.

This isn't really true. All Rust functions that can panic are fallible, independently of whether their return type is `Result` or not.

There are idioms to use `Result` for recoverable failures and panics for "harder-to-recover" failures, but that's about it, and people do use `catch_unwind` on `main` to make their web-servers live forever, and they are doing it right, IMO (this is one of the many justified usecases of `catch_unwind`).

If the errors would actually be non-recoverable, `catch_unwind` wouldn't need to exist.

Also, even if you think as panics as "errors that will kill this thread", your program has multiple threads, and resources leaked by one thread continues to be leaked (e.g. memory is not reclaimed by the OS until the whole process exits), so you still have a leak.

Re: Why should I have written ZeroMQ in C, not C++ (2012)

#150

Earlier quoted context omitted.

In Rust, this destructor is perfectly fine: impl Drop for Foo { fn drop(..) { self.cleanup(); self.free_memory(); } } even if `self.cleanup()` panics. When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. If there is a `catch_unwind` somewhere, these leaks will grow over time. The same code in C++: ~foo() { this->cleanup(); this->free_m…

> In Rust, this destructor is perfectly fine: Sort of; it's very rare. You don't really write free_memory, unless you're doing some very specific unsafe things. > When that happens, `self.free_memory` will never be called, and memory will be leaked if `panic=unwind`, which is the default behavior. It will be leaked if panic=unwind and if you use catch_panic. catch_panic is not used very much. Partially because panic=…

> There isn't, which is why it isn't done, which is why your point confused me :)

This shows why it was a bad decision. It allows doing something in the language (unwinding from destructors), that a lot of code needs to protect against (e.g. all the standard library collections, all collections in general, all types that own a resource, etc.), for absolutely no added value (doing that isn't a useful thing to do).

Aborting the process if `Drop::drop` unwinds would have simplified both the language and the programs written in the language without downsides.

That doing that was a good idea was known (CERT C++ requires non-throwing destructors), and C++ actually made a backward incompatible change in C++11 to fix that (making destructors `noexcept(true)` by default, e.g., see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n316...).

Post reply on HN