2010-08-12 40 views
5

Tôi nghe nói rằng việc ném ngoại lệ vào/từ thư viện C++ có thể nguy hiểm, đặc biệt là với các tệp DLL và đặc biệt nếu mã gọi và thư viện được biên dịch với các trình biên dịch khác nhau. Có sự thật này? Có an toàn miễn là tôi dính vào các thư viện tĩnh không? Lưu ý rằng tôi không nói về việc sử dụng nội bộ ngoại lệ trong thư viện mà thôi, tôi cũng muốn ném chúng sâu vào mã gọi điện thoại :)Không an toàn để ném ngoại lệ từ các thư viện C++ được liên kết tĩnh?

Chỉ cần làm rõ: Giả sử tôi có một thư viện tĩnh được biên dịch xác định lớp Foo như này:

class Foo 
{ 
public: 
    // Constructor 
    Foo() 
    { 
     /* ... Do stuff ... */   
     if (stuffwentwrong) 
      throw(123); // We throw an integer error code (to make it simple) 
    } 
}; 

Và một số anh chàng sử dụng nó như thế này:

try 
{ 
    Foo foo_object; 
} 
catch (int i) 
{ 
    std::cout << "Oh bum. Code: " << i; 
} 

rằng sẽ được an toàn không?

+0

Có những vấn đề (khoảng 15 năm trước đây) này đã được giải quyết (trừ khi bạn đang làm việc sôi nổi như tự động tải/dỡ DLL tất cả bởi chính mình). Nếu bạn chỉ cần sử dụng một DLL thì bạn sẽ ổn thôi. –

Trả lời

3

và đặc biệt là nếu mã gọi điện thoại và thư viện được biên dịch với trình biên dịch khác nhau

Bạn thường không thể trộn C trình biên dịch khác nhau ++ mà không có tương thích ABI. Vì vậy, ví dụ, bạn không thể ném ngoại lệ từ thư viện được biên soạn với MSVC và cố gắng bắt nó với GCC.

Nhưng nếu không, bạn thường không gặp vấn đề gì.

Ghi chú nhỏ:

MSVC có một số mô hình ngoại lệ không tương thích, không pha trộn chúng.

+0

có rất nhiều tinh tế khác mà làm cho nó nguy hiểm nói chung mặc dù. Ví dụ: nếu DLL được biên dịch với một phiên bản CRT khác, bạn sẽ bị vặn (ví dụ: gỡ lỗi so với bản phát hành hoặc đa luồng so với chuỗi đơn).Ngoài ra, CRT lưu trữ trạng thái nhất định ở cấp mô-đun, không phải cấp độ quy trình (ví dụ hModule, hoặc thông tin theo dõi bộ nhớ), vì vậy khi bạn truyền các đối tượng phụ thuộc CRT qua các ranh giới DLL, tất cả những thứ này có thể không đồng bộ. Và các lỗi ở thời gian chạy, và có thể rất tinh tế/đầu trầy xước. Nói chung tránh điều này. – tenfour

0

Ví dụ bạn đưa ra sẽ hoạt động tốt, tuy nhiên với DLL, nếu bạn tình cờ ném một ngoại lệ được phân bổ, bạn sẽ gặp sự cố nếu người dùng DLL cố gắng giải phóng ngoại lệ được cấp phát.

3

đối với GCC Với, có ít nhất một trường hợp ngoại lệ đánh bắt từ GCC tạo chia sẻ thư viện có thể có vấn đề, ví dụ: khi quên xuất throw loại có thể từ thư viện chia sẻ khi tầm nhìn biểu tượng là "hidden" theo mặc định. Trang GCC Visibility Wiki có chi tiết tốt về vấn đề và cách ngăn chặn sự cố.

Tôi không chắc chắn nếu Windows DLL có vấn đề tương tự, nhưng có vẻ như có khả năng.

1

Lưu ý chung khi nói đến các tệp DLL và ngoại lệ:

Không triển khai lớp ngoại lệ trong dòng tiêu đề. Bạn sẽ kết thúc với vtables trùng lặp và thông tin RTTI, dẫn đến ngoại lệ không bị bắt gặp trong mã sử dụng (do trùng lặp, ngoại lệ được coi là loại khác).

Chi tiết:

http://marcmutz.wordpress.com/2010/08/04/fun-with-exceptions/

Các vấn đề liên quan