Tôi có thư viện C++ mà tôi đang cố gắng chạy trên Mac OS X với Clang. Thư viện bao gồm một DLL và một bài kiểm tra Unit-Test. Nó biên dịch tốt với GCC và MSVC, với GCC, tôi sử dụng các cài đặt sau:Bắt các loại ngoại lệ có nguồn gốc không thành công trên Clang/MacOS X
- Thư viện này được biên soạn với
-fvisibility=hidden
- Tất cả các lớp tiếp xúc được đánh dấu một cách rõ ràng như
__attribute__(visibility("default"))
- Thư viện có một số lớp ngoại lệ, có nguồn gốc từ
std::runtime_error
. Tất cả các lớp như vậy được đánh dấu để hiển thị mặc định. Có một lớp gốcLibraryException
từ đó có nhiều ngoại lệ cụ thể hơn. - On GCC, tôi sử dụng
-std=c++0x
, với kêu vang, cả hai thư viện và các đơn vị kiểm tra thực thi được xây dựng với-stdlib=libc++ -std=c++11
Trên Mac OS X, khuôn khổ kiểm tra đơn vị tại thất bại, bởi vì trường hợp ngoại lệ là loại sai . I E. một thử nghiệm như thế này không thành công:
// bla.foo() throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo(), CustomException)
// This works however
TEST_THROWS (bla.foo(), LibraryException)
Tôi xác minh rằng loại thông tin và vtable của các lớp ngoại lệ tùy chỉnh của tôi được xuất bằng cách sử dụng nm -g library.dylib | c++filt -p -i
. Điều này có vẻ là trường hợp cho tất cả các trường hợp ngoại lệ ... cái quái gì đang diễn ra ở đây? Tôi đã cố gắng để gỡ lỗi trên các lỗi, và tôi thấy như thế nào loại chính xác đang được ném trong thư viện và chưa cùng loại không thể bị bắt trong thực thi thử nghiệm đơn vị. Có điều gì đặc biệt cần thiết với Clang để làm việc này không? Tôi đang sử dụng khung googletest mới nhất từ SVN để kiểm tra.
Một chương trình thử nghiệm nhỏ thể hiện cùng một vấn đề:
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";
}
Nó cũng không ví dụ như khi một ngoại lệ boost::lexical_cast
được ném từ Thư viện.
Chắc chắn trông giống như một lỗi ... bạn đã tự làm lại bản thân trình phá hủy hay nó là cấu trúc mặc định được xây dựng? Với gcc 4.3.2, tôi nhận được một cảnh báo nếu tôi khai báo một destructor không có 'throw()' specifier khi kế thừa từ 'exception'. –
Tôi redeclared nó trong LibraryException như ~ LibraryException() throw(); nếu không, GCC 4.6 phàn nàn rằng mặc định có một đặc tả ném không chính xác hoặc một cái gì đó tương tự. – Anteru