X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,TW_CX,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Message-ID: <4C1A2829.3090602@gmail.com> Date: Thu, 17 Jun 2010 14:50:33 +0100 From: Dave Korn User-Agent: Thunderbird 2.0.0.17 (Windows/20080914) MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: C++ app segfaults in libstdc++ References: <4C198B44 DOT 6040803 AT cwilson DOT fastmail DOT fm> <4C1A11EF DOT 9000405 AT gmail DOT com> In-Reply-To: <4C1A11EF.9000405@gmail.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com 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 +#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 #include -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