TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

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

223 pointsby marcobambiniabout 5 years ago

25 comments

leni536about 5 years ago
1. That &quot;C equivalent&quot; 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 &quot;C equivalent&quot; is returning an error code, which has other problems.<p>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&lt;T&gt; (where T is the given class).<p>3. Throwing in destructors is not a C++ problem, it&#x27;s a general semantic problem around resources that aren&#x27;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.
评论 #22939476 未加载
评论 #22938409 未加载
评论 #22937453 未加载
评论 #22937047 未加载
评论 #22942450 未加载
jcelerierabout 5 years ago
Author asserts that &quot;The decoupling between raising of the exception and handling it, that makes avoiding failures so easy in C++, makes it virtually impossible to guarantee that the program never runs info undefined behaviour.&quot; (and all the woes he encounters afterwards stems from trying to avoid exceptions due to that assertion). But that is not my experience at all. Exceptions are much more reliable than error codes - there will always be a case where you forget to propagate an error you got, but you cannot &quot;forget&quot; to propagate an exception... (and if you do, you can always run a debugger post-mortem to get a nice stacktrace of where the exception was thrown - `coredumpctl gdb` is a super nice tool for that on Linux systems with systemd). And languages without exceptions just end up with a galore of `if err != nil { panic(err); }` or similar horrors...<p>Also, regarding &quot;compiler is likely to produce more efficient code.&quot;, benchmarks have shown that exceptions are generally faster : <a href="http:&#x2F;&#x2F;nibblestew.blogspot.com&#x2F;2017&#x2F;01&#x2F;measuring-execution-performance-of-c.html" rel="nofollow">http:&#x2F;&#x2F;nibblestew.blogspot.com&#x2F;2017&#x2F;01&#x2F;measuring-execution-p...</a>
评论 #22937364 未加载
评论 #22939946 未加载
评论 #22937168 未加载
评论 #22937446 未加载
gumbyabout 5 years ago
This article is simultaneously both obsolete and completely current.<p>Obsolete in that the C++ committee has addressed almost all of the issues raised (e.g. constructor semantics, xception semantics et al) though the discussion of site-of-error&#x2F;handling-of-error continues unabated.<p>Later versions of C++ (17and 20) are powerful and expressive systems programming languages that aren’t like the object-oriented messes of old.<p>The reason that this article remains completely current is that I suspect the majority, and likely vast majority, of C++ is still written in C++03&#x2F;C++11 and full of dreadful issues like the ones in the article.
评论 #22937358 未加载
评论 #22937151 未加载
评论 #22936977 未加载
评论 #22937294 未加载
cryptonectorabout 5 years ago
I don&#x27;t get it. Exceptions are bad -&gt; don&#x27;t use exceptions. Constructors can fail with exceptions -&gt; use a factory pattern and handle errors explicitly. Destructors can&#x27;t fail: right, so don&#x27;t, and yes, if you need to do finalization that could fail then that has to be explicit (as in C) and you can handle errors there, and yes, that leaves you with half-destructed objects, but so what.<p>No, I think high-level static data typing is very important. Today Rust would be a better language than C++ for this, but C++ is still better than C.
sxyuanabout 5 years ago
It seems like the author&#x27;s main complaints are avoided if one follows the Google C++ style guide, which says:<p>- Don&#x27;t use C++ exceptions<p>- Don&#x27;t do work in constructors (prefer &quot;Init&quot; or factory functions instead)<p><a href="https:&#x2F;&#x2F;google.github.io&#x2F;styleguide&#x2F;cppguide.html" rel="nofollow">https:&#x2F;&#x2F;google.github.io&#x2F;styleguide&#x2F;cppguide.html</a><p>There may be other reasons to prefer C over C++, but if you don&#x27;t like exceptions, you don&#x27;t have to use them.
评论 #22937173 未加载
评论 #22936921 未加载
评论 #22936713 未加载
评论 #22957125 未加载
commandlinefanabout 5 years ago
I&#x27;ve always felt that object-oriented programming as a concept (that is, define structures and then define functions to operate on them together) is useful: object-oriented programming as a language design is not. Once you understand what encapsulation, inheritance and polymorphism <i>are</i>, you&#x27;re much better off using them as guidance to structure your program in an otherwise procedural language like C than wrestling with a few dozen new keywords and an opaque specification.
评论 #22937206 未加载
评论 #22936931 未加载
评论 #22938574 未加载
评论 #22936724 未加载
lisperabout 5 years ago
Oh, the irony of preferring to use C in order to avoid undefined behavior. C is every bit as much a minefield of undefined behavior as C++ is.<p><a href="https:&#x2F;&#x2F;www.i-programmer.info&#x2F;news&#x2F;184-cc&#x2F;11862-c-undefined-behavior-depressing-and-terrifying.html" rel="nofollow">https:&#x2F;&#x2F;www.i-programmer.info&#x2F;news&#x2F;184-cc&#x2F;11862-c-undefined-...</a>
dangabout 5 years ago
A thread from 2018: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=18668669" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=18668669</a><p>2015: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=9577988" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=9577988</a><p>2013: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=6220049" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=6220049</a><p>2012: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=4455225" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=4455225</a><p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3953434" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3953434</a>
jdashgabout 5 years ago
I was trying to figure out if this was satire.<p>C++ gives you strictly more tools, particularly for guaranteeing reliability, and they&#x27;re all optional.<p>What particularly laughable here is the split ctor&#x2F;init pattern is allegedly driving them towards C, whereas C doesn&#x27;t even give you dtors! If you&#x27;re forgetting your init calls, are you really telling me you&#x27;re not going to forget your destructor call? There are plenty of approaches besides split-init anyway, but it feels like the author feels pulled towards C for other reasons, and is looking for reasoning after the fact. C is not a magic bullet for simpler code!<p>C is useful for solving social problems with deciding what features and patterns of C++ to use, if you&#x27;ve given up on code review and style guidelines. If you decide that&#x27;s you, good luck! You&#x27;ll need it.
评论 #22937726 未加载
评论 #22936802 未加载
herrkaninabout 5 years ago
I&#x27;m a bit confused about the current state of ZeroMQ and its relatives. There&#x27;s nanomessage, which for some reason didn&#x27;t pan out and is superseded by nng(?), but ZMQ still seem to be the most popular option. If I were to pick a broker-less message queue today, what should I pick?
评论 #22936656 未加载
评论 #22936652 未加载
fxtentacleabout 5 years ago
I believe the placement new operator does exactly what is needed here. It&#x27;ll take a self-allocated block of memory and run the constructor on it, thereby avoiding the risk of system generated exceptions as execution stays purely in user code. Basically, it allows you to use a C++ constructor like a C init function.
weyhhweyhabout 5 years ago
Are there any good resources (websites&#x2F;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?
评论 #22937565 未加载
deepsunabout 5 years ago
From Java pro view:<p>In Java it&#x27;s a sin to do anything complex in constructors. You only assign fields and maybe, maybe, call some pure static function to assign a computed field.<p>That mainly comes from unit-testing perspective -- so you can mock the parameters for a unit object _before_ the object does anything.<p>If you really need to do something complex to initialize those fields, it&#x27;s better to extract them to different service class (and call it, ahem, Factory).<p>So the code looks more like his C example, but wrapped in classes.
elcritchabout 5 years ago
This has become one of those “classic” articles. Worth a read if you haven’t. The bits about exceptions reminded me of an article on Nim‘s “goto” exceptions implementation [1]. The implementation appears to be a combo of error codes and goto’s to automatically propagate the exception. It performs well and works on embedded devices, although I’ve only done a smaller project in Nim on an Arduino based board. It’s odd having a serial port print stack traces. Careful a slow serial line can lead to a slow printout though!<p>Nim with the new ARC GC and move semantics seems to make a nice language for embedded development or for creating re-useable libraries. Rust seems promising but so much embedded work is still C&#x2F;C++ only at some level, while Nim compiles to C&#x2F;C++ nicely.<p>1: <a href="https:&#x2F;&#x2F;nim-lang.org&#x2F;araq&#x2F;gotobased_exceptions.html" rel="nofollow">https:&#x2F;&#x2F;nim-lang.org&#x2F;araq&#x2F;gotobased_exceptions.html</a>
kazinatorabout 5 years ago
ZeroMQ is a behemoth; for something that just handles communication, it compiles to like 660KB of i386 machine code. Is there an OS kernel with networking, virtual memory, USB and a file system hiding in there?
deckerabout 5 years ago
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 &#x27;alternatives considered&#x27; section or some other legitimate arguments like &quot;I&#x27;m OCD and I just can&#x27;t handle the fact that if I want to alphabetize the methods in the declaration for a base class it&#x27;s a breaking change in terms of binary compatibility for a shared library.&quot;
hedoraabout 5 years ago
Given the article’s age, the issues brought up are reasonable.<p>Now that it’s 8 years later, I’d summarize it as:<p>- exceptions were a bad idea (in any language); don’t use them.<p>- implementation inheritance and constructors &#x2F; destructors that contain non-trivial logic were a bad idea; don’t use them.<p>This basically means you shouldn’t be writing idiomatic object oriented code.<p>Fortunately, C++ supports other programming paradigms, and in current C++, you can avoid both these historical warts; they shouldn’t affect day-to-day systems programming or error handling.
laurowynabout 5 years ago
I think there&#x27;s a lot of merit to this post, but it really shows its age. Modern C++ typically suffers from only the last point raised - exceptions during destruction, but that goes against the all good C++ practices.<p>Overall, the author&#x27;s approach to exception use is flawed. It&#x27;s bad form to use exceptions for code flow purposes, as per their example. If you throw an exception in the same block that catches the exception, you&#x27;ve wasted a whole lot of time doing something an IF-statement could solve trivially.<p>All projects that I have worked on that use C++ has declared that exceptions should be used in exceptional circumstances only - that is, when you cannot handle the error in the current code block and the function interface does not support returning enough information to the caller to detail what went wrong. An exception is more than just throwing your hands in the air and saying &quot;I can&#x27;t do that&quot; - it has context, purpose, history. Getting rid of exceptions breaks some of the fundamental design concepts of the language.<p>2-step initialisation is the only way around errors during construction whilst forbidding exceptions. But 2-step init breaks a fundamental rule of RAII - the constructor acquires the resource and establishes all class invariants or throws an exception if that cannot be done. If the constructor is not allowed to throw exceptions, as per the language&#x27;s standardised interface for constructors, then my library or application needs to be modified to support whatever process a third party library has defined as appropriate. There is a wide surface for bugs to creep in, let alone costing me time, money and effort in supporting whatever interface they&#x27;ve come up with.<p>If an object has been constructed, it should be in a valid state unless an exception has been thrown, in which case I&#x27;m told what went wrong. If I can fix it before the stack is fully unwound, I can save the day. but if there&#x27;s nothing I can do, the exception has to roll to the top as that&#x27;s the only other option. That then begs the question; should I catch all exceptions at the top level and prevent crashing, or should I crash and allow whatever system I&#x27;m running under to restart me? That depends on the project, but typically I&#x27;d let it go. systemd should bring me back, docker should restart me, kubernetes should restart my pod, etc etc. If I focus on what is within my control, and delegate everything else, the system will be cleaner and much more maintainable.<p>I&#x27;ve never come across a situation where exceptions during destruction is a problem, but am very interested in any examples. C++ standards define that you _can_ throw exceptions, but you shouldn&#x27;t for the exact reason raised in the article - the process will be terminated as there&#x27;s nothing else that can be done. If there aren&#x27;t any destructors containing the throw keyword, it&#x27;s not likely to throw an exception - OOM or other system exceptions are still possible, but why are you allocating memory in a destructor? destructors just need to release resources and clear down the object, it shouldn&#x27;t be requesting more resources. Thinking about saving the object state before exit? wrong place to do it.
评论 #22938090 未加载
评论 #22937757 未加载
评论 #22938395 未加载
评论 #22937865 未加载
malkiaabout 5 years ago
Writing in C++ means that the C++ library you are using becomes a dependency. Probably not an issue, if you have the source code to all libraries that you use, but maybe an issue if you are vendor and try to support not only all possible modern compilers, but what they target to (platforms, runtimes, models, etc.)<p>With just &quot;C&quot;, not &quot;C&quot; only at the interface part, you can avoid that. Even to the point that your binary artifact (library) can be reused safely between DEBUG and RELEASE. Alternatively you need to ship this as shared statically linked to CRT library (which lots of vendors do), but it&#x27;s general pain in the ass... for all platforms.<p>So that is the hidden cost of C++, even if your interface is still &quot;C&quot;.
评论 #22938343 未加载
Gaelanabout 5 years ago
@mods can we change the title to &quot;Why I should have&quot; instead of &quot;why should I have&quot;?<p>The current title reads like a question with the question mark omitted (&quot;Why should I have used C, not C++?&quot;) which, at least to me, implies that it&#x27;s saying C++ was the right decision. The thesis of the post looks like the opposite.
bra-ketabout 5 years ago
previous discussion: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3953434" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3953434</a>
评论 #22938025 未加载
netdurabout 5 years ago
The only thing I dislike about C++ is that I can&#x27;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.
评论 #22938224 未加载
评论 #22938250 未加载
评论 #22939018 未加载
arendtioabout 5 years ago
Somehow it reads like a love letter to Go, but I bet he wouldn&#x27;t like the Garbage Collector ;-)
Ididntdothisabout 5 years ago
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.<p>One would be a way to automatically clean up resources. Maybe something like “defer” in Go.<p>I wonder if templates would fit into C. STL is super useful.<p>A real string type would be good too.
评论 #22936845 未加载
评论 #22938896 未加载
评论 #22936854 未加载
评论 #22936820 未加载
评论 #22936803 未加载
bullenabout 5 years ago
By now he probably realizes that the Java version is what he was looking for all along: <a href="https:&#x2F;&#x2F;github.com&#x2F;zeromq&#x2F;jeromq" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;zeromq&#x2F;jeromq</a><p>Why C&#x2F;C++ coders don&#x27;t even write &quot;Hello World&quot; in Java SE before drifting away into rewriting the ball bearing (1907) part of the wheel is beyond me.<p>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 the VM.<p><pre><code> public static void main(String[] args) { while(1) { try { &#x2F;&#x2F; do everything, and always throw unchecked &#x2F;&#x2F; Exceptions unless you need the programmer to &#x2F;&#x2F; handle the problem } catch(Custom c) { &#x2F;&#x2F; here we can react to the exact problem the &#x2F;&#x2F; parent programmer devised } catch(Exception e1) { &#x2F;&#x2F; something &quot;normal&quot; happened that would have &#x2F;&#x2F; generated completely random behavior with &#x2F;&#x2F; machine code } catch(Error e2) { &#x2F;&#x2F; something &quot;critical&quot; happened that would have &#x2F;&#x2F; generated a segfault with machine code!!! } finally { Thread.sleep(10); } } } </code></pre> The above code will never cause you to loose sleep. You can pretend there is a way to do this in any other programming language, but only C# would be able to and it is lackluster in so many other domains.<p>C will not help you with exceptions or concurrency, it will punish you into believing Rust is the solution.<p>C++ Exceptions are complete garbage, the only good part of C++ are std API (not implementation apparently) and Objects for structure, not for data (cache-misses).<p>Java does not crash and has the same performance as machine code, that is why it is the leading server language in the world.<p>Goodbye karma! Xo<p>Edit: that was fast!<p>Edit2: Please comment if you downvote.
评论 #22938086 未加载
评论 #22937840 未加载
评论 #22938061 未加载
评论 #22938102 未加载