C++ app segfaults in libstdc++

Dave Korn dave.korn.cygwin@gmail.com
Thu Jun 17 13:30:00 GMT 2010


On 17/06/2010 13:15, Dave Korn wrote:
> On 17/06/2010 03:41, Charles Wilson wrote:
> 
>> Any ideas?
> 
>   Yes, I have one:
> 
>>   catch (modexc e) {
>>     std::cerr << "caught: " << e.what () << '\n';
>>     if (dlclose (handle))
>>       {
>>         std::cerr << "dlclose failed: " << dlerror () << '\n';
>>         return 1;
>>       }
>>     return 0;
>>   }
> 
>   You're unloading the module, before the exception that it threw goes out of
> scope.
> 
>   At this time, the modexc object e has not yet been destructed, the catch is
> still 'live', and when you attempt to exit the catch block, __cxa_end_catch
> gets fatally confused.  The live exception still contains pointers into where
> the dll used to be loaded: it has typeinfo there, and a pointer to the
> module's inlined instance of the ~modexc() dtor.
> 
>   I think the rule is: Don't unload a shared library while you still have a
> live C++ object from it, unless that object is a POD.

  Also, I think this is basically an ODR violation problem, like we used to
have with std::strings between main executable and shared libs.  The module
and the main each have their own entirely separate definitions of class
modexc, and each uses only the one it knows.  I think to do this properly, the
class needs to be dllexported from the module, and the main needs to dllimport
it, rather than have its own second implementation.

  (Of course, if you do it that way, main then is statically as well as
dynamically linked to the module, since it imports the ctors, dtors, vtables
and typeinfo et al from the DLL; but there's no other way to get it correct.)

  After annotating the header with attributes:

diff -rpu orig//module.cpp fixed2/module.cpp
--- orig//module.cpp    2010-06-17 14:47:21.812500000 +0100
+++ fixed2/module.cpp   2010-06-17 14:47:36.218750000 +0100
@@ -1,4 +1,5 @@
 #include <iostream>
+#define IN_MODULE
 #include "module.h"

 int modbar (void) throw (modexc)
Only in fixed2: module.dll
diff -rpu orig//module.h fixed2/module.h
--- orig//module.h      2010-06-17 14:47:21.812500000 +0100
+++ fixed2/module.h     2010-06-17 14:47:34.781250000 +0100
@@ -1,6 +1,13 @@
 #include <exception>
 #include <string>
-class modexc : public std::exception {
+
+#ifndef IN_MODULE
+#define DLL __attribute__ ((dllimport))
+#else
+#define DLL __attribute__ ((dllexport))
+#endif
+
+class DLL modexc : public std::exception {
 public:
   modexc (std::string str) : message (str) { }
   ~modexc () throw () { }

you need to add "-Wl,--out-implib,libmodule.dll.a -Wl,--export-all-symbols" to
the library link command and "-L. -lmodule" to the main exe link command.
(Also I don't see any need for export-all-symbols on the main exe.)

  To summarize the summary of the summary: C++ is complicated.

    cheers,
      DaveK


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list