2016-05-30 77 views
2

我見過很多人在我的團隊檢查的空指針這樣的:爲什麼std :: nothrow在gcc(4.9)中按預期工作?

SomeClass *pSc = new SomeClass; 
    if (NULL == pSc) 
    { 
     // cope with error 
    } 

我知道這是行不通的,因爲在C++ new操作符拋出一個std :: bad_alloc異常,而不是返回NULL。我也知道std :: nothrow可以使他們預期的真正發生。所以我寫了這樣一個例子:

#include <iostream> 
    #include <limits> 
    #include <new> 
    using namespace std; 

    void myNewHandler() 
    { 
     std::cerr << "Failed to allocate memory!" << std::endl; 
    } 

    int main(int argc, char* argv[]) 
    { 
     //std::new_handler oldHandler = std::set_new_handler(myNewHandler); 

     int *pLotsMem = new(std::nothrow) int[std::numeric_limits<long long>::max()]; 
     if (nullptr == pLotsMem) 
     { 
      std::cerr << "Allocation failed" << std::endl; 
      return -1; 
     } 
     else 
     { 
      delete[] pLotsMem; 
      pLotsMem = nullptr; 
     } 

     //std::set_new_handler(oldHandler); 

     return 0; 
    } 

是的,我想演示std :: set_new_handler的用法。令我驚訝的是,即使這樣也行不通。 new運算符仍然拋出異常(std :: bad_array_new_length,std :: bad_alloc的派生類),然後終止程序。

任何想法爲什麼這失敗了? 如何檢查gcc中新運算符返回的指針?

+0

它在叮噹中按預期工作 –

+0

是的!它也適用於vC++編譯器。但我不知道爲什麼它無法在gcc中工作。 –

+1

使用'GCC 6.1.0',它不會編譯,除非您將大小減小到合法數量。然後它按預期工作。 – Galik

回答

4

相信不相信,這是符合標準的行爲:

5.3.4/7

在noptr新說明符中的表達是錯誤的,如果:
[...] - 其值爲分配對象的大小將超過實現定義的限制(附錄B);其值爲。或
[...]

如果表達式,轉換到std ::爲size_t之後,是一個核心恆定 表達和表達是錯誤的,是形成不良的節目。 否則,新表達錯誤的表達不 呼叫分配函數和通過拋出的 異常的類型,將匹配 類型爲std的處理程序(15.3):: bad_array_new_length終止(18.6.2.2) 。當 表達式的值爲零時,調用分配函數來分配一個沒有元素的 數組。

總之,非投擲分配功能甚至沒有叫,異常由新的表達本身拋出。

我假定不使用現代C++版本,因爲在那些std::numeric_limits<long long>::max()標記爲constexpr並且是芯常量表達式,其產生編譯時間錯誤。

鐺,大概具有比長林斯頓的最大值更高實現定義的限制集,繞過這夸克的C++。

+0

謝謝!我將nullptr改回爲NULL,並在沒有「-std = C++ 11」選項的情況下編譯代碼。這一次它按預期工作。最現代的C++是如此不同,對我來說有很多東西需要學習。 –

+2

http://wg21.link/cwg1992 –

相關問題