Ho una libreria C++ che sto cercando di eseguire su Mac OS X con Clang. La libreria è costituita da una DLL e un eseguibile di Test unità. Si compila bene con GCC e MSVC, con GCC, io uso le seguenti impostazioni:Tipi di eccezioni derivate dalla cattura non riesce su Clang/MacOS X
- La libreria viene compilata con
-fvisibility=hidden
- Tutte le classi esposte sono esplicitamente contrassegnati come
__attribute__(visibility("default"))
- La biblioteca dispone di alcune classi di eccezioni, derivato da
std::runtime_error
. Tutte queste classi sono contrassegnate per visibilità predefinita. Esiste una classe radiceLibraryException
da cui derivano eccezioni più specifiche. - Su GCC, io uso
-std=c++0x
, con clangore, sia la biblioteca e l'eseguibile test di unità è costruita con-stdlib=libc++ -std=c++11
In Mac OS X, il framework di unit test ora viene a mancare, perché le eccezioni sono di tipo sbagliato . Cioè un test come questo non riesce:
// bla.foo() throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo(), CustomException)
// This works however
TEST_THROWS (bla.foo(), LibraryException)
ho verificato che il typeinfo e vtable delle mie classi di eccezioni personalizzate viene esportato utilizzando nm -g library.dylib | c++filt -p -i
. Questo sembra essere il caso per tutte le eccezioni ... cosa diavolo sta succedendo qui? Ho provato a eseguire il debug degli errori, e vedo come viene lanciato il tipo corretto nella libreria e tuttavia lo stesso tipo non può essere catturato nell'eseguibile del test dell'unità. C'è qualcosa di speciale richiesto con Clang per farlo funzionare? Sto usando l'ultimo framework googletest di SVN per i test.
Un piccolo programma di test presenta lo stesso problema:
try {
funcThatThrowsCustomExceptionFromLibraryDylib();
} catch (CustomException& e) {
// doesn't get here
} catch (LibraryException& e) {
// does get here
// after demangle, this prints CustomException
// Can cast down to CustomException and access the fields as well
std::cout << typeid (e).name() << "\n";
}
Non riesce anche ad esempio quando un'eccezione boost::lexical_cast
viene lanciata dalla Libreria.
Sicuramente sembra un bug ... hai dichiarato di nuovo il distruttore o è il predefinito costruito? Con gcc 4.3.2 viene visualizzato un avviso se dichiaro un distruttore senza l'identificatore 'throw()' quando si eredita da 'exception'. –
L'ho ridichiarato in LibraryException come ~ LibraryException() throw(); in caso contrario, GCC 4.6 si è lamentato del fatto che quello predefinito ha una specifica di lancio errata o qualcosa di simile. – Anteru