<?xml version="1.0" encoding="UTF-8" standalone="yes"?><oembed><version><![CDATA[1.0]]></version><provider_name><![CDATA[Software is Crap]]></provider_name><provider_url><![CDATA[https://davmac.wordpress.com]]></provider_url><author_name><![CDATA[davmac]]></author_name><author_url><![CDATA[https://davmac.wordpress.com/author/davmac/]]></author_url><title><![CDATA[Clever hacks are just&nbsp;not.]]></title><type><![CDATA[link]]></type><html><![CDATA[<p><a href="https://davmac.wordpress.com/2015/07/19/tale-of-two-abis/">Just recently I wrote about</a> the clever &#8220;dual ABI&#8221; hack found in GCC 5&#8217;s implementation of the standard C++ library. I quipped at the end of that post:</p>
<blockquote><p>I suspect the right way to handle changing ABI is to do it the way it’s always been done – by bumping the soname.</p></blockquote>
<p>Having recently done some work on a C++ project, I&#8217;ve discovered an issue present in the dual ABI implementation. What seemed like trivial code to handle an exception from attempting to open a non-existent file just wasn&#8217;t working. I worked it down to the following test case:</p>
<pre style="padding-left:30px;">#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;typeinfo&gt;

int main(int argc, char **argv)
{
    using namespace std;
    using std::ios;
    
    ifstream a_file;
    a_file.exceptions(ios::badbit | ios::failbit);
    
    try {
        a_file.open("a-non-existent-file", ios::in);
    }
    catch (ios_base::failure &amp;exc) {
        cout &lt;&lt; "Caught exception on attempt to open non-existing file." &lt;&lt; endl;
    }
    catch (exception &amp;exc) {
        cout &lt;&lt; "Caught standard exception: " &lt;&lt; typeid(exc).name() &lt;&lt; endl;
    }

    return 0;
}</pre>
<p>Surprisingly, this fails to work properly (prints the wrong message) when compiled with a straight &#8220;g++ -o simple simple.cc&#8221;. It works correctly when compiled instead with &#8220;g++ -D_GLIBCXX_USE_CXX11_ABI=0 -o simple simple.cc&#8221;. I would have filed a bug, but it seems the problem is <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145">known</a>.</p>
<p>This is a pretty major bug. Any C++ program that handles I/O errors by catching the appropriate exceptions just isn&#8217;t going to work. Furthermore, this isn&#8217;t just a minor problem; having to separate out implementations of iosbase and derived classes for the two ABIs would significantly reduce the benefit of even having the dual ABI. The problem with &#8220;clever&#8221; hacks like the dual ABI libstdc++ is that they are (1) often not so clever and are (2) always most definitely hacks. The proposed solution? Heap more hacks on top so the first hack works:</p>
<blockquote>
<p id="comment_text_0" class="bz_comment_text">One option to make both forms work would be to hack the EH runtime to make handlers for std::ios_base::failure able to catch std::ios_base::failure[abi:cxx11] objects, and vice versa, creating an object of the other type on the fly.</p>
</blockquote>
<p>Urgh. Just urgh.</p>
<p>What really annoys me most about this nonsense is that the one sane option I have &#8211; stripping out the &#8216;abi_tag&#8217; nonsense from the source, re-compiling libstdc++ and calling it libstdc++.so.7 &#8211; would probably cause me problems further down the track, because third-party binaries are going to want the new ABI with the old soname (and even if I didn&#8217;t care about those, I&#8217;d still be one version number up from the official libstdc++ from that point on, which feels like it could cause problems).</p>
]]></html></oembed>