Tengo una biblioteca C++ que estoy intentando ejecutar en Mac OS X con Clang. La biblioteca consta de un DLL y un ejecutable Unit-Test. Se compila bien con GCC y MSVC, con GCC, utilizo los siguientes ajustes:La captura de tipos de excepciones derivadas falla en Clang/MacOS X
- La biblioteca se compila con
-fvisibility=hidden
- Todas las clases expuestas están marcados explícitamente como
__attribute__(visibility("default"))
- La biblioteca tiene algunas clases de excepción, derivado de
std::runtime_error
. Todas esas clases están marcadas para visibilidad predeterminada. Existe una clase raízLibraryException
de la cual se derivan excepciones más específicas. - En GCC, utilizo
-std=c++0x
, con sonido metálico, la biblioteca y el archivo ejecutable de prueba de unidad se construye con-stdlib=libc++ -std=c++11
En Mac OS X, el marco de pruebas unitarias ahora no funciona, porque las excepciones son del tipo incorrecto . Es decir. una prueba como esta falla:
// bla.foo() throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo(), CustomException)
// This works however
TEST_THROWS (bla.foo(), LibraryException)
I verificado que la typeinfo y vtable de mis clases de excepciones personalizadas se exporta con nm -g library.dylib | c++filt -p -i
. Este parece ser el caso para todas las excepciones ... ¿Qué diablos está pasando aquí? He intentado depurar los errores y veo cómo se está lanzando el tipo correcto en la biblioteca y, sin embargo, el mismo tipo no se puede capturar en el ejecutable de la prueba unitaria. ¿Hay algo especial requerido con Clang para que funcione? Estoy usando el último framework de googletest de SVN para probar.
Un pequeño programa de prueba presenta el mismo 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";
}
También falla, por ejemplo, cuando una excepción boost::lexical_cast
se lanza desde la Biblioteca.
Definitivamente parece un error ... ¿ha redeclarado el destructor usted mismo o es el construido por defecto? Con gcc 4.3.2 recibo una advertencia si declaro un destructor sin el especificador 'throw()' al heredar de 'exception'. –
Lo he vuelto a declarar en LibraryException como ~ LibraryException() throw(); de lo contrario, GCC 4.6 se quejó de que el predeterminado tiene una especificación de tiro incorrecta o algo similar. – Anteru