Boost C++ Libraries: Ticket #754: boost::any - typeid comparison across shared boundaries https://svn.boost.org/trac10/ticket/754 <pre class="wiki">typeid comparison (using == operator) fails under certain platforms and certain conditions. For me it fails for template classes at least (std::vector for example) when I use it across shared boundaries. Therefore boost::any doesn't work in these cases and throws bad_any_cast exception even when it returns it holds the same type I am about to cast it to (I am using gcc-4.1). boost::python has already solved this by comparing string representations of types under problematic platforms. This works well in all cases but can be a bit slower. In boost/python/type_id.hpp: // for this compiler at least, cross-shared-library type_info // comparisons don't work, so use typeid(x).name() instead. It's not // yet clear what the best default strategy is. # if (defined(__GNUC__) &amp;&amp; __GNUC__ &gt;= 3) \ || defined(_AIX) \ || ( defined(__sgi) &amp;&amp; defined(__host_mips)) \ || (defined(linux) &amp;&amp; defined(__INTEL_COMPILER) &amp;&amp; defined(__ICC)) # define BOOST_PYTHON_TYPE_ID_NAME # endif I would say the same thing should be applied to boost::any In boost/any.hpp: template&lt;typename ValueType&gt; ValueType * any_cast(any * operand) { return operand &amp;&amp; operand-&gt;type() == typeid(ValueType) ? &amp;static_cast&lt;any::holder&lt;ValueType&gt; *&gt;(operand-&gt;content)-&gt;held : 0; } should be replaced with: template&lt;typename ValueType&gt; ValueType * any_cast(any * operand) { # if (defined(__GNUC__) &amp;&amp; __GNUC__ &gt;= 3) \ || defined(_AIX) \ || ( defined(__sgi) &amp;&amp; defined(__host_mips)) \ || (defined(linux) &amp;&amp; defined(__INTEL_COMPILER) &amp;&amp; defined(__ICC)) return operand &amp;&amp; !strcmp( operand-&gt;type().name(), typeid(ValueType).name() ? &amp;static_cast&lt;any::holder&lt;ValueType&gt; *&gt;(operand-&gt;content)-&gt;held : 0; # else return operand &amp;&amp; operand-&gt;type() == typeid(ValueType) ? &amp;static_cast&lt;any::holder&lt;ValueType&gt; *&gt;(operand-&gt;content)-&gt;held : 0; # endif } btw: I am aware that this may cause performance drops and it would be great if there was a switch for that or something for people that aren't using boost::any across shared boundaries. </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/754 Trac 1.4.3 kulik Sat, 06 Jan 2007 10:49:06 GMT <link>https://svn.boost.org/trac10/ticket/754#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:1</guid> <description> <pre class="wiki">Logged In: YES user_id=1620918 Originator: YES This is IMO a really critical bug and can be very easily solved. Many applications won't work if they use some kind of module mechanism with shared objects. I spend many hours smashing my head till I realised what's causing it. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>alnsn</dc:creator> <pubDate>Tue, 16 Jan 2007 20:38:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/754#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:2</guid> <description> <pre class="wiki">Logged In: YES user_id=369903 Originator: NO Since it's a bug in C++ implementation, I don't see why I should replace ASAP a portion of good C++ with non-portable code. I would rather suggest you first check if this bug is already in a queue of your C++ vendor and post a link here. In a meantime, I will study boost.python workaround and other libraries. There ought to be portable type_info somewhere. Boost should not have multiple clones of this functionality. This is especially important for non-portable code. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>kulik</dc:creator> <pubDate>Tue, 16 Jan 2007 20:58:10 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/754#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:3</guid> <description> <pre class="wiki">Logged In: YES user_id=1620918 Originator: YES I know it's kinda a gcc specific problem, but if you watch Visual C++ output, it's technically doing the same, string comparison of the type representation. Gcc tries to be faster by comparing memory adressess of structures characterizing the types, these structures are unfortunately linked separately into each boundary, thus causing this problem when using boost::any across the boundary. official gcc bug entry: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23628 There are various references of the problem on gcc.gnu.org mailing list: http://gcc.gnu.org/ml/gcc/2002-05/msg01970.html http://gcc.gnu.org/ml/gcc/2003-10/msg01360.html (unanswered) However this bug prevails from somewhere around gcc-3 on. Before gcc-3 textual comparison was made to compare types (this is how many compilers do it nowadays). PS: The same problem also exists for dynamic_cast, type comparison fails there too and casts are invalid across shared boundaries. (shared boundary - for example .dll or .so, the problem surfaces when I boost::any_cast something from application in code from the shared object or vice versa) I apologise for priority bumping this bug, it has really been irritating me for a long time. PS: dynamically loading shared objects as RTLD_GLOBAL seems to solve this bug, but I consider this a workaround. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>nasonov</dc:creator> <pubDate>Wed, 29 Aug 2007 09:08:19 GMT</pubDate> <title>owner, status changed; severity set https://svn.boost.org/trac10/ticket/754#comment:4 https://svn.boost.org/trac10/ticket/754#comment:4 <ul> <li><strong>owner</strong> changed from <span class="trac-author">alnsn</span> to <span class="trac-author">nasonov</span> </li> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">new</span> </li> <li><strong>severity</strong> → <span class="trac-field-new">Problem</span> </li> </ul> Ticket Marshall Clow Wed, 29 Aug 2007 14:28:14 GMT component, description changed https://svn.boost.org/trac10/ticket/754#comment:5 https://svn.boost.org/trac10/ticket/754#comment:5 <ul> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">any</span> </li> <li><strong>description</strong> modified (<a href="/trac10/ticket/754?action=diff&amp;version=5">diff</a>) </li> </ul> Ticket staffan.spam at gimaker se Sun, 16 Dec 2007 21:06:23 GMT <link>https://svn.boost.org/trac10/ticket/754#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:6</guid> <description> <p> I was bit my this bug as well, and it really wasn't fun to track down. </p> <p> Using RTLD_GLOBAL isn't possible when using libltdl to load the DSO, since lt_dlopenext() doesn't expose a way to control the flags used with dlopen. </p> <p> The only fix for this is for us to maintain a patched version of any.hpp, that has the above workaround implemented - which seems like a hopelessly fragile solution. </p> <p> It doesn't seem like the GCC crowd will *ever* fix this, so can you <strong>please</strong> consider implementing a workaround for it in Boost? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Mike Dickey</dc:creator> <pubDate>Mon, 11 Feb 2008 23:10:32 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/754#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:7</guid> <description> <p> &lt;banging head against the wall&gt;Just for the record: I lost a day and a half to this bug too... until I was finally able to figure out what seemed to be happening and prove to myself that it wasn't my code that was at fault. Tough one too, because it works fine on some platforms (Windows, OSX, etc.) but not others (i.e. Linux). I agree that this is a really nasty bug b/c it makes Boost's behavior non-deterministic across platforms, which I thought was part of the whole point... &lt;/banging head against the wall&gt; </p> </description> <category>Ticket</category> </item> <item> <dc:creator>ulit at eikon dot com</dc:creator> <pubDate>Wed, 25 Feb 2009 10:59:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/754#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:8</guid> <description> <p> Same here as found by Mike and staffan: painful and long search why boost::any didn't work across library boundaries. </p> <p> When the patch above is not acceptable: please consider an additional cast function (e.g. "any_cast_by_name") which does the type comparision based on strings. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sat, 06 Jun 2009 17:38:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/754#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/754#comment:9</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/754#comment:6" title="Comment 6">staffan.spam at gimaker se</a>: </p> <blockquote class="citation"> <p> I was bit my this bug as well, and it really wasn't fun to track down. </p> <p> Using RTLD_GLOBAL isn't possible when using libltdl to load the DSO, since lt_dlopenext() doesn't expose a way to control the flags used with dlopen. </p> </blockquote> <p> libltdl always uses RTLD_GLOBAL, assuming RTLD_GLOBAL is defined for your platform. See libltdl/ltdl.c in libtool. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>nasonov</dc:creator> <pubDate>Sun, 13 Sep 2009 13:16:30 GMT</pubDate> <title>status, resolution changed https://svn.boost.org/trac10/ticket/754#comment:10 https://svn.boost.org/trac10/ticket/754#comment:10 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/56168" title="Fix #754 (boost::any - typeid comparison across shared boundaries). ">[56168]</a>) Fix <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/754" title="#754: Bugs: boost::any - typeid comparison across shared boundaries (closed: fixed)">#754</a> (boost::any - typeid comparison across shared boundaries). </p> Ticket