C new失敗的處理

2021-07-22 23:06:57 字數 2767 閱讀 5650

我們都知道,使用 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)

……處理失敗……

// 標準推薦做法一。

trycatch(bad_alloc &memexp)

// 標準推薦做法二

是使用 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()

int main()

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 int...