Live data from Hacker News

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

250bpm.com

111–120 of 170 posts

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

#111
post #81

Earlier quoted context omitted.

True, I recently returned to C++ after many years absence and I'm thrilled with all the good stuff that has been added BUT it took me quite a while to learn how I'm going to unlearn/relearn my old practices.

I decided to treat it as if it was a language I had never seen before. That helped a lot.

Likewise, but also I now realise, after a long break I really like programming with "system languages". I get a certain amount of satisfaction that I don't get with higher-level languages, where I spend so much time plugging together half-built crappy modules.

Partly this is because I have realised, I like knowing the nuts and bolts of what is going on in a computer and solving problems with consideration of how it will run. It also has less magic and crappy layers going on.

C++ has evolved a lot from what I used many years ago, and it looks mostly for the better, thankfully we have escaped the 'thou must OO' age.

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

#112
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…

> 3. Throwing in destructors is not a C++ problem, it's a general semantic problem around resources that aren't guaranteed to be freed up successfully. They are a pain in any language and you can only do best-effort approaches for not leaking them. C++ is quite good here, arguably quite better than Rust, since in C++ you can add a `noexcept(true)` clause to your destructor, and if it throws, your program terminates.…

Note that noexcept(true) in destructors has been the default for a while. It was a breaking change, but there is very little code that can handle throwing destructors that in practice jad little consequences.

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

#113
post #77

The only thing I dislike about C++ is that I can't declare private fields privately, I can use private: but it is there in header... in C I can just declare struct Foo; in header then implement it without expose its gusts.

Are you familiar with the PIMPL idiom?

very nice, I do that but never header of PIMPL

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

#114

Are there any good resources (websites/books) to learn some of the new ways of doing things in C++ 20 vs older. Eg something that shows the old patterns with pitfalls and what replaces them in C++ 20?

Bjarne Strsoustroup's short book "A Tour of Modern c++" fits the bill, and was written for the same purpose.

I recommend, reading it now, it really fits the bill for someone coming back to C++ after many years.

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

#115

Earlier quoted context omitted.

Correct me if I'm wrong, but panics themselves are fairly rare. That's not the case in C++ where "throw" is a keyword you are expected to use for error handling. If you take this to a Java example, a panic is more like an "Error" and less like an "Exception". That is to say, in rust, if something panics it is a sign of a major bug that shouldn't have any option for recovery. With all that said, the same concept exist…

Conceptually, panics should be rare, because one firing means that some sort of unexpected problem has occurred. However, the real world is not "conceptually." I don't think there's any real data about how often they happen, but at least my experience is that tools I write in Rust rarely end up showing me panic output. > That's not the case in C++ where "throw" is a keyword you are expected to use for error handling.…

A fun example here is rust-analyzer: we implement cancellation via unwinding. This is not technically a panic, but the mechanism is the same, and it more or less is invoked every time a user types something in a file.

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

#116

When I did C++ I always ended up using a very small subset of it. No exceptions, no inheritance besides a few interfaces. But in general I agree with his point. There are a few things C could improve though. One would be a way to automatically clean up resources. Maybe something like “defer” in Go. I wonder if templates would fit into C. STL is super useful. A real string type would be good too.

All the things you mentioned can be found in Zig! [1] It's exception semantics are very similar to Go, but unlike Go, you have to handle the error. It has constructs like `defer` and `errdefer` which allow you do clean up at the end of the scope or on exception respectively. It has support for Generics and Metaprogramming without having to resort to preprocessor macros. It just released v0.6.0 and is actively in deve…

Zig definitely looks interesting. I may use it in a smaller project to try out.

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

#117
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…

> 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 is the given class).

This comment criticizes an article written in 2012 about a project developed starting in 2007 for not using a technique that debuted in the 2017 edition of ISO C++. For projects that could force all consumers to use C++11 or later, it'd be straightforward to add your own.

The idea of doing so in a cross-compiler way when you need to support the original ISO standard or C++0x in the late 2000s sounds very problematic.

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

#118

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…

Unless I'm misunderstanding your comment, you can make panics abort rather than unwind. https://doc.rust-lang.org/edition-guide/rust-2018/error-hand...

You are misunderstanding the comment, because it's specifically talking about the case when panic is set to unwind and there is catch_unwind handler.

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

#119
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…

> 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 is the given class). This comment criticizes an article written in 2012 about a project developed starting in 2007 for not using a technique that debuted in the 2017 edition of ISO C++. For projects that could force all consum…

It's not hard to write an optional in C++ 2003, and likely can be done in C++ 98.

If you don't like that, return a T*, null if not created correctly.

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

#120

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 seems like they're trying to solve a problem (manual destructor call to free memory) that is important in other languages but not rust on account of borrowing. Even in the author's examples I feel like it's a problem directly solved by lifetimes, since all the reasoning about freeing that memory is already there.

Interestingly they picked the best possible case to showcase rust's strengths, where the free happens on drop. If it were a case where you needed strict control over where that memory came from and _when_ it gets freed, C would seem like a nice fit, but rust is great when you only care that the memory is gone once your variable's out of scope.

Post reply on HN