5

Biểu thức new trong khối try ném một ngoại lệ bad_alloc trong máy tính của tôi.Làm thế nào để `e.what()` in "phân bổ xấu"?

Lưu ý rằng mệnh đề catch nhận một đối tượng ngoại lệ theo giá trị, không phải bằng tham chiếu. Làm thế nào đến e.what() in "bad allocation"? Tôi nghĩ nó sẽ bị cắt.

#include <iostream> 

int main() 
{ 
    try 
    { 
     int* p = new int[0x1F000000]; 
    } 
    catch(std::exception e) 
    { 
     std::cout << e.what() << std::endl; 
    } 
} 
+2

Bạn chỉ cố gắng phân bổ = ~ 1.9375GB trong chương trình của bạn. Bạn đang biên dịch 32 bit? Bạn thậm chí có rất nhiều RAM trong máy của bạn? – FailedDev

+0

@GMan Trình biên dịch là MS VS 2008 – Belloc

Trả lời

13

Visual Studio (Dinkumware?) Sử dụng triển khai std::exception chứa bộ nhớ trong † cho thư. (Hoàn thành với một nhà xây dựng không chuẩn chấp nhận một chuỗi.)

Do đó, không có công văn ảo nào thực sự cần thiết để nhận được thông báo lỗi, nó tồn tại bất kỳ lần cắt nào.

Một triển khai chính thống hơn sẽ thực sự in một thông báo ngoại lệ chung, bởi vì đối tượng dẫn xuất đã bị cắt. (Có hiệu quả, MS đã std::exceptionstd::runtime_error tương đương. Không có gì sai với điều này là vì giá trị trở lại của std::exception::what là thực hiện xác định, nhưng nó giải thích kết quả của bạn.)


† lưu trữ nội bộ ở đây được sử dụng một cách lỏng lẻo. Nó không có bộ đệm nội bộ, nhưng có const char*bool. Các const char* điểm đến tin nhắn (giá trị trả về của what()), và bool là một lá cờ xác định nếu bộ đệm sẽ bị xóa.

Đó là như thế này:

class msvc_exception // for exposition 
{ 
public: 
    msvc_exception(const char* msg) : 
    mMsg(msg), 
    mDoDelete(false) 
    {} 

    msvc_exception(const std::string& msg) : 
    mMsg(copy_string(msg)), 
    mDoDelete(true) 
    {} 

    virtual ~msvc_exception() 
    { 
     if (mDoDelete) 
      delete [] mMsg; 
    } 

    virtual const char* what() const throw() 
    { 
     return mMsg ? mMsg : "unknown"; 
    } 

private: 
    const char* copy_string(const std::string& str) 
    { 
     const char* result = new char[str.size() + 1]; 

     std::copy(str.begin(), str.end(), result); 
     result[str.size()] = 0; // null-terminate 

     return result; 
    } 
}; 

Bạn thấy bây giờ mà bad_alloc công trình như thế này:

class msvc_bad_alloc : // for exposition 
     public msvc_exception 
    { 
    public: 
     msvc_bad_alloc() : 
     msvc_exception("bad_alloc") // note: a static string, no dynamic storage 
     {} 
    }; 

Cắt lát không ảnh hưởng đến thông điệp vì thông báo "tồn tại" trong lớp cơ sở.

trình biên dịch khác, như GCC và LLVM, thực hiện nó hơn một chút thẳng forwardly:

class orthodox_exception 
{ 
public: 
    orthodox_exception(){} 
    virtual ~orthodox_exception() {} 

    virtual const char* what() const throw() 
    { 
     return "orthodox_exception"; 
    } 
}; 

class orthodox_bad_alloc : 
    public orthodox_exception 
{ 
public: 
    const char* what() const throw() 
    { 
     return "orthodox_bad_alloc"; 
    } 
}; 

Ở đây, cắt sẽ ảnh hưởng đến kết quả của bạn. (Điều đó nói rằng, sau khi tất cả điều này: luôn luôn bắt bằng cách tham khảo.)

+0

Vì vậy, bạn đang nói rằng 'ngoại lệ' giữ một bản sao của chuỗi ký tự cho tất cả các lớp dẫn xuất của nó? – Belloc

+0

@ user1042389: Ngôn ngữ của tôi hơi lỏng lẻo, cho phép tôi chỉnh sửa. – GManNickG

+0

Khá rõ ràng ngay bây giờ. Cảm ơn rất nhiều. – Belloc