2011-11-30 403 views
5

try塊中的new表達式會在我的計算機中拋出bad_alloc異常。'e.what()`怎麼打印出「壞分配」?

請注意,catch子句按值接收異常對象,而不是引用。 e.what()怎麼打印"bad allocation"?我認爲它會被切片。

#include <iostream> 

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

你只是試圖在你的程序中分配=〜1.9375GB。你正在編譯32位?你的機器裏有甚麼RAM? – FailedDev

+0

@GMan編譯器是MS VS 2008 – Belloc

回答

13

的Visual Studio(Dinkumware的?)使用的std::exception一個實現,它包含消息內部存儲†。 (完成接受字符串的非標準構造函數)。

因此,實際上不需要虛擬調度來獲取錯誤消息,它可以在任何切片中生存。

更正統的實現將確實打印一個通用的異常消息,因爲派生的對象被切掉。 (實際上,MS取得了std::exceptionstd::runtime_error等價的。有沒有錯的,因爲std::exception::what返回值是實現定義的,但它說明了你的結果。)


†內部存儲這裏泛指。它沒有內部緩衝區,但它有一個const char*和一個boolconst char*指向消息(返回值爲what()),而bool是一個標誌,用於確定是否應刪除緩衝區。

是這樣的:

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; 
    } 
}; 

您現在看到bad_alloc是這樣工作的:

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

切片不影響消息,因爲消息「存在」的基類。

其他編譯器,如GCC和LLVM,實現多一點直向前:

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"; 
    } 
}; 

這裏,切片會影響您的結果。 (也就是說,畢竟這是總是按照參考)

+0

所以你說'exception'爲所有派生類保留字符串的副本? – Belloc

+0

@ user1042389:我的語言有點鬆散,允許我編輯。 – GManNickG

+0

現在很清楚。非常感謝。 – Belloc