<story><title>Memory management in C programs (2014)</title><url>http://nethack4.org/blog/memory.html</url></story><parent_chain><item><author>deathanatos</author><text>&amp;gt; &lt;i&gt;plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without [exceptions].&lt;/i&gt;&lt;p&gt;I would not consider C++ code that eschews exceptions &amp;quot;modern&amp;quot;. To eschew exceptions almost always entails giving up RAII, and if you give up RAII you&amp;#x27;ve done yourself a huge disservice: you&amp;#x27;re now stuck manually managing memory and resources, and suffering all the bugs that come with that. While RAII does not outright prevent these bugs (which is one of the reasons I&amp;#x27;m a huge fan of Rust), coding along its principles greatly reduces the risk that you will run into problems.&lt;p&gt;If you&amp;#x27;re wondering: giving up exceptions means a constructor has no way to signal failure, as the result of a ctor in C++ is always either an exception, or a constructed object. Most &amp;quot;no exceptions&amp;quot; C++ code I&amp;#x27;ve seen opts to construct what I call &amp;quot;zombie objects&amp;quot;; internally, the object tracks that an error has occurred, and all uses of the real object must be first checked against that internal error flag to ensure the object isn&amp;#x27;t a zombie (or if it is, then error). The object is effectively a null pointer, and has all the trouble that entails.&lt;p&gt;(I also won&amp;#x27;t pretend that exceptions aren&amp;#x27;t without problems; in particular, the argument against them because you can&amp;#x27;t tell, at a particular point in a function&amp;#x27;s code, if an exception can occur, or where it would be caught, is completely valid, but no different in many popular languages, such as Python, C#, and in some ways, Java. However, I think the advantages of RAII — and exceptions — outweigh their disadvantages.)&lt;p&gt;&amp;gt; &lt;i&gt;It just has to be written so that most functions manually propagate error codes they receive&lt;/i&gt;&lt;p&gt;When I&amp;#x27;ve had to write C, I&amp;#x27;ve found this to be exceptionally tedious to do correctly, and all too easy to ignore.</text></item><item><author>comex</author><text>I&amp;#x27;m going to claim that the problem being solved here fundamentally comes from attempting to shoehorn early exit into an ancient codebase that wasn&amp;#x27;t designed for it, via longjmp.  Exceptions can be a handy language feature, but plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without them.  It just has to be written so that most functions manually propagate error codes they receive, potentially after manually unwinding some core state.  C code can be written that way too: the manual cleanup that must be written then extends to mundane buffer freeing, but that&amp;#x27;s a tractable and local requirement; no need for complicated global reasoning around static buffers and custom allocation schemes.</text></item></parent_chain><comment><author>flohofwoe</author><text>RAII (or rather the only useful part of the idea: that the destructor is called when an object goes out of scope) without exceptions is totally fine if you&amp;#x27;re not too dogmatic about initialising &lt;i&gt;everything&lt;/i&gt; (especially not things that can go wrong) in the constructor but instead have one or more separate init methods with a return value. The only important part is to cleanup everything in the destructor. This is all IMHO of course, but I&amp;#x27;ve been writing C++ code for 20 years just fine without ever thinking &amp;#x27;gee it would be nice to use exceptions here&amp;#x27;.</text></comment>
<story><title>Memory management in C programs (2014)</title><url>http://nethack4.org/blog/memory.html</url></story><parent_chain><item><author>deathanatos</author><text>&amp;gt; &lt;i&gt;plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without [exceptions].&lt;/i&gt;&lt;p&gt;I would not consider C++ code that eschews exceptions &amp;quot;modern&amp;quot;. To eschew exceptions almost always entails giving up RAII, and if you give up RAII you&amp;#x27;ve done yourself a huge disservice: you&amp;#x27;re now stuck manually managing memory and resources, and suffering all the bugs that come with that. While RAII does not outright prevent these bugs (which is one of the reasons I&amp;#x27;m a huge fan of Rust), coding along its principles greatly reduces the risk that you will run into problems.&lt;p&gt;If you&amp;#x27;re wondering: giving up exceptions means a constructor has no way to signal failure, as the result of a ctor in C++ is always either an exception, or a constructed object. Most &amp;quot;no exceptions&amp;quot; C++ code I&amp;#x27;ve seen opts to construct what I call &amp;quot;zombie objects&amp;quot;; internally, the object tracks that an error has occurred, and all uses of the real object must be first checked against that internal error flag to ensure the object isn&amp;#x27;t a zombie (or if it is, then error). The object is effectively a null pointer, and has all the trouble that entails.&lt;p&gt;(I also won&amp;#x27;t pretend that exceptions aren&amp;#x27;t without problems; in particular, the argument against them because you can&amp;#x27;t tell, at a particular point in a function&amp;#x27;s code, if an exception can occur, or where it would be caught, is completely valid, but no different in many popular languages, such as Python, C#, and in some ways, Java. However, I think the advantages of RAII — and exceptions — outweigh their disadvantages.)&lt;p&gt;&amp;gt; &lt;i&gt;It just has to be written so that most functions manually propagate error codes they receive&lt;/i&gt;&lt;p&gt;When I&amp;#x27;ve had to write C, I&amp;#x27;ve found this to be exceptionally tedious to do correctly, and all too easy to ignore.</text></item><item><author>comex</author><text>I&amp;#x27;m going to claim that the problem being solved here fundamentally comes from attempting to shoehorn early exit into an ancient codebase that wasn&amp;#x27;t designed for it, via longjmp.  Exceptions can be a handy language feature, but plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without them.  It just has to be written so that most functions manually propagate error codes they receive, potentially after manually unwinding some core state.  C code can be written that way too: the manual cleanup that must be written then extends to mundane buffer freeing, but that&amp;#x27;s a tractable and local requirement; no need for complicated global reasoning around static buffers and custom allocation schemes.</text></item></parent_chain><comment><author>kabdib</author><text>I&amp;#x27;ve not seen a large production C++ code base that did anything with exceptions other than to catch them, record some debug information and restart.&lt;p&gt;This is especially true when third party code is involved. C++ is hard enough to get right without exceptions; dealing with failure in bodies of code that you didn&amp;#x27;t write and maybe don&amp;#x27;t have control over (or even source code of) is death on wheels.&lt;p&gt;If that means the code I&amp;#x27;m working on isn&amp;#x27;t modern . . . I think that&amp;#x27;s fine. But the first volume (of three?) of Herb Sutter&amp;#x27;s &lt;i&gt;Exceptional C++&lt;/i&gt; should be enough to convince anyone that dealing with exceptions &amp;quot;correctly&amp;quot; is time better spent eschewing exceptions and restructuring your code so you can do &lt;i&gt;worthwhile&lt;/i&gt; hard things.</text></comment>