<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Comments for page &quot;Why should I have written ZeroMQ in C, not C++ (part I)&quot;</title>
		<link>http://250bpm.com/blog:4/comments/show</link>
		<description></description>
				<copyright></copyright>
		<lastBuildDate>Sat, 01 Aug 2015 21:42:45 +0000</lastBuildDate>
		
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2318778</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2318778</link>
				<description></description>
				<pubDate>Wed, 17 Jun 2015 06:16:08 +0000</pubDate>
				<wikidot:authorName>yourfriendlybutcher</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I just read the article and I think the author doesn't have much understanding of C++. Let's analyse it:</p> <blockquote> <p>However, what's great for avoiding straightforward failures becomes a nightmare when your goal is to guarantee that no undefined behaviour happens. 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.</p> </blockquote> <p>I do not see from where that conclusion originates. Functions that are being called (and potentially fail with an error) should be decoupled from the caller. It doesn't matter if the error is propagated as an exception or a simple code. Error codes can be silently ignored, while exceptions can't, which means you are more likely to introduce bugs while using error codes. If you ignore an error condition and go on, your process might go into undefined behaviour territory. An exception will propagate to the nearest handler, cleaning every object along the way.</p> <blockquote> <p>int rc = fx ();<br /> if (rc != 0)<br /> handle_error ();</p> </blockquote> <blockquote> <p>int rc = fx ();<br /> if (rc != 0)<br /> throw std::exception ();</p> </blockquote> <p>These are not equivalent - far from it.</p> <blockquote> <p>The problem with that is that you have no idea of who and where is going to handle the exception.</p> </blockquote> <p>As it should be. Why should you care who handles the error? In your example, the function fx() obviously doesn't care - just informs that an error happened. You are advocating coupling callees with callers.</p> <blockquote> <p>(code examples)<br /> It's far more readable and — as a bonus — compiler is likely to produce more efficient code.</p> </blockquote> <p>First - it's not equivalent, since you also need to jump out after the error in C. The most common way I see with C programmers is using goto for that task (because you usually need to release resources and there is no RAII in C), which isn't readable at all and can introduce bugs. Can you recall scoping rules with goto out of your head? I don't think so.<br /> Second - if you forget about jumping out, your code will just go on thinking no error was generated.<br /> Third - you have no evidence of the compiler producing that much better code for the programmer to care. When it comes to trading safety for efficiency, you should go with the safety the exceptions provide you with.<br /> Fourth - I find exceptions far more readable - &quot;if X happened, generate error Y&quot;. What's not readable about that?</p> <blockquote> <p>However, it doesn't end there. Consider the case when the exception is not handled in the function that raises it. In such case the handling of the error can happen anywhere, depending on where the function is called from.</p> </blockquote> <p>That is exactly the point. Callee should not care who handles its errors. When a C function returns an error code, it doesn't care who handles it. The same logic applies to exceptions. Once again you are trying to tie callees with callers.</p> <blockquote> <p>As you fix individual bugs you'll find out that you are replicating almost the same error handling code in many places. Adding a new function call to the code introduces that possibility that different types of exceptions will bubble up to the calling function where there are not yet properly handled. Which means new bugs.</p> </blockquote> <p>If you don't handle an exception, the default handler will (terminating the process with an error message). If you don't handle an error code in C - nothing will inform you of that. Your process will go on in an erroneous state thinking everything is ok. Good luck debugging such errors.</p> <blockquote> <p>If you don't give up on the &quot;no undefined behaviour&quot; principle, you'll have to introduce new exception types all the time to distinguish between different failure modes. However, adding a new exception type means that it can bubble up to different places. Pieces of code have to be added to all those places, otherwise you end up with undefined behaviour.</p> </blockquote> <p>First - you won't end up with undefined behaviour, since the exception propagation is well defined by the Standard. You'll end up with the default handler which will show you the error message.<br /> Second - similar logic applies to error code. If you create a new error code, you need to handle it. If you don't, your process will silently go into some undefined state.</p> <blockquote> <p>Well, the problem is that exception specifications are just a tool to handle the problem of exponential growth of the exception handling code in a more systematic manner, but it doesn't solve the problem itself. It can even be said it makes it worse as now you have to write code for the new exception types, new exception handling code *and* new exception specifications.</p> </blockquote> <p>That really doesn't make sense. What is that problem that exceptions don't solve and error codes do? Please define it. Also - what exception specifications? If you're talking about throw(&#8230;) in declarations, those were always a bad idea and were discouraged. Now, they're deprecated and should never be used.</p> <blockquote> <p>Consider what happens when initialisation of an object can fail. Constructors have no return values, so failure can be reported only by throwing an exception. However, I've decided not to use exceptions.</p> </blockquote> <p>And that is your problem there. You decided to go against the language features and you ended up with some absurd semi-constructed states, which you need to handle manually. If you followed the language, that is:</p> <ul> <li>An object is considered constructed (initialized) when its constructor returns with no exception.</li> <li>With RAII, all your resources should be released in the destructor, making resource handling automatic.</li> </ul> <p>you'd find that your code is both safer and simpler. Object could be either constructed or not. Error would be signalled on failed constructions. Resources would be automatically freed.<br /> Instead you made a little hell for yourself, where you need to take that semi-constructed state into account, potentially introducing bugs.</p> <blockquote> <p>Now you say: But that's just a consequence of your artificial restriction of not using exceptions! If exception is thrown in a constructor, C++ runtime cleans the object as appropriate and there is no 'semi-initalised' state whatsoever!</p> <p>Fair enough. However, it's beside the point.</p> </blockquote> <p>No, it's not beside the point. The whole point is about you fighting the language, instead of using its features to make safe code.</p> <blockquote> <p>And that is not a reasonable option for an infrastructure component with the need to be very robust in the face of failures.</p> </blockquote> <p>As a person who is making such &quot;infrastructure components&quot;, as you called them, I claim you are totally wrong on that front. Proper usage of exceptions and proper usage of language features make your code resistant to failures and very safe. Fighting against it is what lead you to this mess, and you try to blame the language for it.</p> <blockquote> <p>Moreover, even if initialisation wasn't a problem, termination definitely is. You can't really throw exceptions in the destructor. Not because of some self-imposed artificial restrictions but because if the destructor is invoked in the process or unwinding the stack and it happens to throw an exception, it crashes the entire process.</p> </blockquote> <p>Right - you should not throw form the destructor (they are noexcept now, in fact). Try to think about more closely - you are releasing resources and you encounter an error. If this is not critical and the process can continue, you can safely not throw. If it it's critical, you should terminate because, well, it's critical.</p> <blockquote> <p>Thus, if termination can fail, you need two separate functions to handle it</p> </blockquote> <p>No, just follow RAII. You'll get a safe and reliable way of automatically releasing resources in a single function - the destructor.</p> <blockquote> <p>However, once you introduce separate init functions, the number of states starts to grow.</p> </blockquote> <p>So you see why your idea of semi-states is bad. Why do you advocate it then?</p> <blockquote> <p>With objects like these it's almost impossible to guarantee predictable behaviour.</p> </blockquote> <p>You created a problem which doesn’t really exist, if you follow the simple rules. You then created a really bad workaround to that problem. And, in the end, you list the reasons why your solution is bad. That's absurd.</p> <blockquote> <p>To summarise the above, I believe that requirement for fully-defined behaviour breaks the object-oriented programming model. The reasoning is not specific to C++. It applies to any object-oriented language with constructors and destructors.</p> </blockquote> <p>Pretty much every piece of code, which is made with proper fashion, proves you wrong. Don't fight the language, but learn to use it to your advantage. You'll find all your problems are really artificial.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2301239</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2301239</link>
				<description></description>
				<pubDate>Fri, 22 May 2015 21:24:51 +0000</pubDate>
				<wikidot:authorName>mark</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>(This was supposed to be a top-level comment. Usability problem uncovered.)</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2301236</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2301236</link>
				<description></description>
				<pubDate>Fri, 22 May 2015 21:21:04 +0000</pubDate>
				<wikidot:authorName>mark</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Can you make an example for a destructor that can fail? For example if an attempt to close a file fails (which it should never do) then the appropriate action would be to log the error and simply do nothing else.</p> <p>The first point of yours was that certain exception patterns are awkward. I agree - so simply don't do it this way. Don't use exceptions for control flow. If, when throwing, you need to know who catches the error then it is a misuse of exception handling and too tight of a coupling. Exceptions are to be treated as special return values that automatically bubble up as a default behavior.</p> <p>If an operation is expected to fail sometimes, and meaningful actions can be taken as a result, then error codes as return values are totally reasonable. They mix with exceptions well.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2300783</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2300783</link>
				<description></description>
				<pubDate>Fri, 22 May 2015 08:12:51 +0000</pubDate>
				<wikidot:authorName>Luca Bruno</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>For data structures you can still mix C with C++, that's what I do. For sets, hashtables, ecc. I use a simple wrapper c++ class that I use from C.<br /> Also there are glib data structures, the hashtable is quite efficient. Glib is very portable.<br /> Just depend on libraries man and don't be afraid. That's what libs are for, for being dependencies.</p> <p>For destructors being invoked at the end of the block, you can do that too with C: <a href="http://echorand.me/site/notes/articles/c_cleanup/cleanup_attribute_c.html">http://echorand.me/site/notes/articles/c_cleanup/cleanup_attribute_c.html</a></p> <p>For virtual methods, I agree it's quite painful, but for a schema that's working in years you can look at gobject and how they do it. For a single class there are two data structures, the instance struct and the class struct. The class struct is where you put the vtable.<br /> That means you have a single vtable for one class instead of having one vtable per-instance.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2300075</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2300075</link>
				<description></description>
				<pubDate>Thu, 21 May 2015 12:59:18 +0000</pubDate>
				<wikidot:authorName>Martin Sustrik</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I did: nanomsg.org</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2300071</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2300071</link>
				<description></description>
				<pubDate>Thu, 21 May 2015 12:46:47 +0000</pubDate>
				<wikidot:authorName>time_t</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>If you think c++ is bad choice for ZeroMQ, why don't you rewrite it using c?</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2298181</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2298181</link>
				<description></description>
				<pubDate>Tue, 19 May 2015 11:14:36 +0000</pubDate>
				<wikidot:authorName>Greg</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>here</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2298179</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2298179</link>
				<description></description>
				<pubDate>Tue, 19 May 2015 11:06:34 +0000</pubDate>
				<wikidot:authorName>Greg</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I don't see what the big deal is hear.</p> <p>While exception do allow the de-coupling of handling from cause, they don't heve to be used that way. You can stop exceptions propagating out of any block and handle, assert or convert to c-style at whatever level you want.</p> <p>In an earlier example you talked about calling a third-party function that could generate any (to you) unknown exception, so just wrap it in a try&#8230;catch(&#8230;) and convert to a return FAIL or asssert, whechever you prefer. How is not using exceptions going to help in this situation?</p> <p>Almost all of C can be mis-used just as easily as C++. At least with exceptions, if you do miss one it will propagate out and you will know, with a missed return check, you may never find out.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2251521</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2251521</link>
				<description></description>
				<pubDate>Mon, 16 Mar 2015 06:49:31 +0000</pubDate>
				<wikidot:authorName>Daniel Kubec</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Perfect arthicle !</p> <p>Abstraction is a technique for managing complexity but these &quot;modern&quot; high-level features often results in more work for machine and developers without any additional values.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2240432</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2240432</link>
				<description></description>
				<pubDate>Thu, 26 Feb 2015 15:43:03 +0000</pubDate>
				<wikidot:authorName>Martin Sustrik</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>If I was to do that, I can as well use raw C, no?</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2239987</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2239987</link>
				<description></description>
				<pubDate>Wed, 25 Feb 2015 19:54:22 +0000</pubDate>
				<wikidot:authorName>dawn</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>for exceptions, use std::nothrow or something like that.<br /> for init and deinit, use 2-phase ctor and dtor.</p> <p>code like this:</p> <p>XX* p = new(std::nothrow) XX(..);</p> <p>if (nullptr == p) { handle_error(); }<br /> else {<br /> auto ret = p-&gt;init();<br /> if (OK != ret) { handle_error(); }<br /> }</p> <p>if ( p-&gt;init_succ() ) {<br /> auto ret = p-&gt;deinit();<br /> if (OK != ret) {<br /> handle_error();<br /> }<br /> }</p> <p>&#8230;</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2229959</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2229959</link>
				<description></description>
				<pubDate>Tue, 10 Feb 2015 22:35:54 +0000</pubDate>
				<wikidot:authorName>Corey Brenner</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>At a guess, you allocate the emergency buffer at the beginning of the program, and then bzero() it, writing the pages and bringing them concretely into your address space.</p> <p>From there, it's a matter of allocating from that particular pool (one of the reasons I think interfaces like malloc() are broken, is because there is no way to supply a generic pool of memory, or to seize a pool from malloc() and have it manage allocations within it).</p> <p>More sophisticated memory handling would benefit C.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2218616</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2218616</link>
				<description></description>
				<pubDate>Wed, 28 Jan 2015 11:19:09 +0000</pubDate>
				<wikidot:authorName>Martin Sustrik</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>The article is talking about idomatic C++ vs. idomatic C.</p> <p>If it was talking about C vs. C++ it would make no sense. C is (more or less) a subclass of C++.</p> <p>As for C++11, C++14 etc., by growing the featureset it's making the problem even more grave. Idiomatic C++ today is definetely a bigger mess than it used to be in 1995. Soon enough it will be as messy as Java :(</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2218447</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2218447</link>
				<description></description>
				<pubDate>Wed, 28 Jan 2015 06:53:32 +0000</pubDate>
				<wikidot:authorName>Rich</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>This point you make IS valid:</p> <p>&quot;This is great when you are OK with 80% or 90% solutions. Errors are sparse and handling them correctly in 90% or cases can mean the problem will be never hit, especially if the program is not used very widely.&quot;</p> <p>However, even a hello world application doesn't have a &lt;10% (we're sayingthat only 10% or less of the logic in the application doesn't handle every single error that can happen absolutely perfectly&#8230;) fault ratio; not even the UNIX kernel has a &lt;10% fault ratio&#8230;.there's always a way to break stuff, why fix it until it needs to be fixed? At which point you know the issue, and how to handle it&#8230;. I can hack Windows and activate it any day of the week -&gt; switching to another language isn't going to stop that.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2218436</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2218436</link>
				<description></description>
				<pubDate>Wed, 28 Jan 2015 06:33:44 +0000</pubDate>
				<wikidot:authorName>Rich</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I have to agree with others C++ is still a better bet, and to touch on Ilja's remark:</p> <p>Move to C++14, not to plain C. C++ i s an extension of C -&gt; You can use any part of C in C++ -&gt; including C syntax. In fact, most beginner C++ courses don't even teach you any C++ at all - it's all C syntax run under a C++ compiler. So in essence it doesn't even make sense to say C would have been better than C++&#8230;.</p> <p>The true trick to any lower level programming language is architecture. How you design your application will make it or break it -&gt; regardless of the actual language used.</p> <p>I'm disappointed seeing all the comments about replacement languages for C; why aren't people working on replacing POSIX APIs with C++ methods over C methods? Why isn't anyone working on replacing C altogether with C++ rather than just letting it be an extension? You know&#8230;making a true C++ runtime in Assembly instead of requiring a C runtime over Assembly? Bet ya that'd be much faster than Go and we wouldn't have to learn any new languages or APIs (well, for the most part - syntax would certainly change a bit for some system methods).</p> <p>Donate me 100k and I'll do it myself - just give me a few years&#8230;</p> <p>The father of C++ isn't dead yet, its only getting better and better and better and better and better.</p> <p>You just need to take the time to work it out. It takes YEARS to LEARN programming, not days -&gt; if you are looking for a single day answer switch to .NET or some other auto-generated non-sense and let the quality speak for itself (but I'm sure you know this already ^^).</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2198031</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2198031</link>
				<description></description>
				<pubDate>Wed, 07 Jan 2015 00:57:15 +0000</pubDate>
				<wikidot:authorName>JoeF</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I know this is a very late comment but for what it's worth:</p> <p>Another alternative to is rust, being developed by Mozilla. It's focus is on being very fast and very safe. The first stable version is due to be released within the next few months and from the little bit I've played around with it, it looks promising as an alternative to C that can be used to build system programs that need to be robust.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2127793</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2127793</link>
				<description></description>
				<pubDate>Thu, 09 Oct 2014 07:08:26 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>That's the whole point. No additional &quot;high-level&quot; features that promote bad coding practices, i.e. separating the source of error from handling the error et c.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2127227</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2127227</link>
				<description></description>
				<pubDate>Wed, 08 Oct 2014 17:14:07 +0000</pubDate>
				<wikidot:authorName>Guy Alster</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>While I agree with the premise that C++ has features that are not adequate for every type of software project, I totally disagree with the conclusion that &quot;I should not have used C++ but rather C&quot;. First, lets state the obvious, which is that C is almost entirely a subset of C++. Hence, you could have still used the &quot;C&quot; semantics interleaved with the goodies that C++ gives you. To continue on that point, Since all programming languages are computationally equivalent, the choice of one language over the other is merely based on the semantics of that language. I would understand (but not agree with) the notion that you decided to use python over C++ because of the productivity gain (e.g. lines of code/hour) or perhaps the maintainability gain. But I just can't understand how using C makes your life easier compared to C++, besides the fact that the compiler restricts you to a certain subset of the features.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2113232</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2113232</link>
				<description></description>
				<pubDate>Fri, 19 Sep 2014 06:34:32 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Yes. See here: nanomsg.org</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:4/comments/show#post-2113230</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:4/comments/show#post-2113230</link>
				<description></description>
				<pubDate>Fri, 19 Sep 2014 06:31:43 +0000</pubDate>
				<wikidot:authorName>Ayub</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Did you actually write it using C instead of C++, will be interesting.</p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>