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…
Why should I have written ZeroMQ in C, not C++ (2012)
141–150 of 170 posts
Re: Why should I have written ZeroMQ in C, not C++ (2012)
#142Re: Why should I have written ZeroMQ in C, not C++ (2012)
#143I 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…
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)
#144Earlier 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.
Re: Why should I have written ZeroMQ in C, not C++ (2012)
#145By 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…
Re: Why should I have written ZeroMQ in C, not C++ (2012)
#146Earlier 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 ?
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)
#147Re: Why should I have written ZeroMQ in C, not C++ (2012)
#148Earlier 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=…
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)
#149Earlier 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=…
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)
#150Earlier 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=…
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...).