C new 失敗的處理

2021-06-07 08:47:08 字數 2837 閱讀 9885

我們都知道,使用 malloc/calloc 等分配記憶體的函式時,一定要檢查其返回值是否為「空指標」(亦即檢查分配記憶體的操作是否成功),這是良好的程式設計習慣,也是編寫可靠程式所必需的。但是,如果你簡單地把這一招應用到 new 上,那可就不一定正確了。我經常看到類似這樣的**:

int* p = new int[size];

if ( p == 0 ) // 檢查 p 是否空指標

return -1;

// 其它**

其實,這裡的 if ( p == 0 ) 完全是沒啥意義的。c++ 裡,如果 new 分配記憶體失敗,預設是丟擲異常的。所以,如果分配成功,p == 0 就絕對不會成立;而如果分配失敗了,也不會執行 if ( p == 0 ),因為分配失敗時,new 就會丟擲異常跳過後面的**。如果你想檢查 new 是否成功,應該捕捉異常:

try catch ( const bad_alloc& e )

據說一些老的編譯器裡,new 如果分配記憶體失敗,是不丟擲異常的(大概是因為那時 c++ 還沒加入異常機制),而是和 malloc 一樣,返回空指標。不過我從來都沒遇到過 new 返回空指標的情況。

當然,標準 c++ 亦提供了乙個方法來抑制 new 丟擲異常,而返回空指標:

int* p = new (std::nothrow) int; // 這樣如果 new 失敗了,就不會丟擲異常,而是返回空指標

if ( p == 0 ) // 如此這般,這個判斷就有意義了

return -1;

// 其它**

******************************=詳解***********************************

首先按c++標準的話,new失敗會丟擲bad_alloc異常,但是有些編譯器對c++標準支援不是很好,比如vc++6.0中new失敗不會丟擲異常,而返回0.

//不支援c++標準的做法如下

double *ptr=new double[1000000];

if( 0 == ptr)

……處理失敗……

//標準推薦做法一。

trydouble *ptr=new double[1000000];

catch(bad_alloc &memexp)

//失敗以後,要麼abort要麼重分配

cerr<

//標準推薦做法二

是使用set_new_handler函式處理new失敗。它在標頭檔案裡大致是象下面這樣定義的:

typedef void (*new_handler)();

new_handler set_new_handler(new_handler p) throw();

可以看到,new_handler是乙個自定義的函式指標型別,它指向乙個沒有輸入引數也沒有返回值的函式。set_new_handler則是乙個輸入並返回new_handler型別的函式。

set_new_handler的輸入引數是operator new分配記憶體失敗時要呼叫的出錯處理函式的指標,返回值是set_new_handler沒呼叫之前就已經在起作用的舊的出錯處理函式的指標。

可以象下面這樣使用set_new_handler:

// function to call if operator new can't allocate enough memory

void nomorememory()

cerr << "unable to satisfy request for memory\n";

abort();

int main()

set_new_handler(nomorememory);

int *pbigdataarray = new int[100000000];

...}

operator new不能滿足記憶體分配請求時,new-handler函式不只呼叫一次,而是不斷重複,直至找到足夠的記憶體。實現重複呼叫的**在條款8裡可以看到,這裡我用描述性的的語言來說明:乙個設計得好的new-handler函式必須實現下面功能中的一種。

·產生更多的可用記憶體。這將使operator new下一次分配記憶體的嘗試有可能獲得成功。實施這一策略的乙個方法是:在程式啟動時分配乙個大的記憶體塊,然後在第一次呼叫new-handler時釋放。釋放時伴隨著一些對使用者的警告資訊,如記憶體數量太少,下次請求可能會失敗,除非又有更多的可用空間。

·安裝另乙個不同的new-handler函式。如果當前的new-handler函式不能產生更多的可用記憶體,可能它會知道另乙個new-handler函式可以提供更多的資源。這樣的話,當前的new-handler可以安裝另乙個new-handler來取代它(通過呼叫set_new_handler)。下一次operator new呼叫new-handler時,會使用最近安裝的那個。(這一策略的另乙個變通辦法是讓new-handler可以改變它自己的執行行為,那麼下次呼叫時,它將做不同的事。方法是使new-handler可以修改那些影響它自身行為的靜態或全域性資料。)

·卸除new-handler。也就是傳遞空指標給set_new_handler。沒有安裝new-handler,operator new分配記憶體不成功時就會丟擲乙個標準的std::bad_alloc型別的異常。

·丟擲std::bad_alloc或從std::bad_alloc繼承的其他型別的異常。這樣的異常不會被operator new捕捉,所以它們會被送到最初進行記憶體請求的地方。(丟擲別的不同型別的異常會違反operator new異常規範。規範中的預設行為是呼叫abort,所以new-handler要丟擲乙個異常時,一定要確信它是從std::bad_alloc繼承來的。想更多地了解異常規範)

·沒有返回。典型做法是呼叫abort或exit。abort/exit可以在標準c庫中找到(還有標準c++庫)。

上面的選擇給了你實現new-handler函式極大的靈活性。

c new失敗處理

在c語言中如果malloc calloc分配記憶體失敗的時候,會返回乙個空指標,但是在 中使用 new 分配記憶體的時候,標準規定new分配失敗時會丟擲異常,因此不能使用如下的方式判斷new是否成功,int p new int size if null p return 如果分配失敗,則以上 將是沒...

C new失敗的處理

我們都知道,使用 malloc calloc 等分配記憶體的函式時,一定要檢查其返回值是否為 空指標 亦即檢查分配記憶體的操作是否成功 這是良好的程式設計習慣,也是編寫可靠程式所必需的。但是,如果你簡單地把這一招應用到 new 上,那可就不一定正確了。我經常看到類似這樣的 int p new int...

C new失敗的處理

我們都知道,使用 malloc calloc 等分配記憶體的函式時,一定要檢查其返回值是否為 空指標 亦即檢查分配記憶體的操作是否成功 這是良好的程式設計習慣,也是編寫可靠程式所必需的。但是,如 果你簡單地把這一招應用到 new 上,那可就不一定正確了。我經常看到類似這樣的 int p new in...