1. 程式人生 > >C++ 處理new分配記憶體失敗

C++ 處理new分配記憶體失敗

轉自:http://www.51testing.com/html/70/n-827070.html

在C++語言中,我們經常會使用new給一個物件分配記憶體空間,而當記憶體不夠會出現記憶體不足的情況。C++提供了兩中報告方式:

  1、丟擲bad_alloc異常來報告分配失敗;

  2、返回空指標,而不會丟擲異常。

  C++為什麼會採用這兩種方式呢?這主要是由於各大編譯器公司設計C++編譯器公司的結果,因為標準C++是提供了異常機制的。例如,VC++6.0中當new分配記憶體失敗時會返回空指標,而不會丟擲異常。而gcc的編譯器對於C++標準支援比較好,所以當new分配記憶體失敗時會丟擲異常。

  究竟為什麼會出現這種情況呢?

  首先,C++是在C語言的基礎之上發展而來,而且C++發明時是想盡可能的與C語言相容。而C語言是一種沒有異常機制的語言,所以C++應該會提供一種沒有異常機制的new分配記憶體失敗報告機制;(確實是如此,早期的C++還沒有加入異常機制)

  其次在返回空指標的實現過程中,C++採用的是malloc/calloc 等分配記憶體的函式,該類函式不會丟擲異常,但是在分配記憶體失敗時會返回“空指標”。

  最後,對於標準的C++,有著比較完善的異常處理機制,所以對於出現異常時,會丟擲響應的異常。對於new分配失敗時,系統會丟擲bad_alloc異常。

  鑑於以上原因,我們在不同的編譯器需要new分配失敗時做不同的處理。例如:

  情況1:

int* p = new int(5);
if ( p == 0 ) // 檢查 p 是否空指標
    return -1;
...

  情況2:

try {
      int* p = new int(5);
        // 其它程式碼
} catch ( const bad_alloc& e ) {
      return -1;
}

  情況1和情況2的程式碼都是對於new失敗時的處理,而針對不同的編譯器,可以這種處理會完全失效。如果在gcc編譯器採用情況1,那麼if(p==0)完全是沒有意義的,因為不管new記憶體分配成功失敗與否,都不會出現p=0的情況。即,如果分配成功,p=0完全不可能;而分配失敗,new會丟擲異常跳過其後面的程式碼。而需要採用情況2的處理方式,即應該來捕捉異常。

  同樣,如果在VC++6.0中採用情況2的程式碼,那麼new分配失敗時,完全不會丟擲異常,那麼捕捉異常也是徒勞的。

  所以在new分配記憶體的異常處理時要特別小心,可以兩種方式聯合使用,來解決跨平臺跨編譯器的難題。

  當然情況2中的異常處理程式碼是最簡單的處理方式,下面我們為其制定一個客戶制定的錯誤處理函式,即new-handler。

typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();

這裡首先定義new-handler函式指標型別,然後定義一個new-handler函式set_new_handler,其引數是指向operator new無法分配足夠記憶體時應該被呼叫的函式。其返回指也是一個指標,指向set_new_handler被呼叫前正在執行(但是馬上就要被替換)的那個new-handler函式。下面設計一個當operator new無法分配足夠記憶體時應該被呼叫的函式:

void noMemoryToAlloc()
{
       std::cerr << "unable to satisfy request for memory\n";

        std::abort();
}

  使用noMemoryToAlloc函式的程式碼為:

int main()
{
       set_new_handler(nomorememory);
       int *pArray = new int[100000000000000L];

...

}

  當operator new無法分配足夠空間時,noMemoryToAlloc就會被呼叫,於是程式就會發出一個錯誤資訊cerr之後,呼叫abort函式結束程式。

  如果operator new無法分配足夠空間時,我們希望不斷呼叫new-handler函式,直到找到足夠記憶體為止,那麼我們的operator new函式就可以設計為:

void *operator new(std::size_t size) throw(std::bad_alloc)
{
        if ( size==0 ) {
             size  = 1;
        }
       while (true) {
            呼叫malloc等記憶體分配函式來嘗試分配size大小的記憶體;
            if ( 分配成功 )
                 return 指向分配得來的記憶體指標;
            new_handler globalHandler  = set_new_handler(0);
            set_new_handle(globalHandler);
            if(globalHandler)
                   (*globalHandler)();
           else
                   throw std::bad_alloc();
       }
}

轉自:http://blog.sina.com.cn/s/blog_9f1c09310101953s.html

 使用new分配記憶體失敗時往往會使用asert()終止程式,但是這隻能在除錯模式下abert函式才能有效,在生產模式下,abert只是一個void指令,所以連程式都跳不出來。

    而當new操作失敗時,一個好的程式不能簡單的終止程式就行了,而是要嘗試去釋放記憶體    如何能在new操作失敗,在丟擲異常之前先把相應的處理做了呢?這就要用到new_handler了,它是在丟擲exception呼叫的。為了指定這個所謂的“記憶體不足處理函式,new_handler”,client必須呼叫set_new_handler,這是標頭檔案提供的函式,用法:    typedef void (*new_handler)()    new_handler set_new_handler(new_handler p) throw();簡單的程式測試:#include "stdafx.h"#include#includeusing namespace std;void NoMoreMemory(){cout<<"Unable to statisty request for memory"<<endl;abort();}int _tmain(int argc, _TCHAR* argv[]){set_new_handler(NoMoreMemory);int *p=new int[536870911];return 0;}注:當operator new 無法滿足記憶體需求時,它會不只一次地呼叫new_handler函式(如果new_handler沒有退出程式的話);它會不斷地呼叫,直到找到足夠的記憶體為止。因此一個良好設計的new_handler函式必須完成下列事情之一:1)讓更多的記憶體可用。這或許能夠讓operator new 的下一次記憶體配置行為成功。實現此策略的方法之一就是在程式起始時配置一大塊記憶體,然後在new_handler第一次被呼叫時釋放之。如此的釋放動作常常伴隨著某種警告資訊,告訴使用者目前的記憶體已經處於低水位,再來的記憶體需求可能失敗,除非有更多的記憶體回覆自由身。2)安裝一個不同的new_handler,如果目前的new_handler無法讓更多的記憶體可用,或許它知道另一個new_handler手上我有比較多的資源。果真如此,目前的new_handler就可以安裝另外一個new_handler以取代自己(只要再呼叫一次set_new_handler即可)。當operator new下次呼叫new_handler函式時,它會呼叫最新安裝的那個。3)卸除掉這個new_handler,也就是說,將null指標傳給set_new_handler,一旦沒有安裝任何new_handler,operator new就會在記憶體配置失敗時丟擲一個型別為std::bad_alloc的exception。4)丟擲一個exception,型別為std::bad_alloc(或者派生型別)。這樣的exception不會被operator new捕獲,所以它們就會傳動到最初踢出記憶體需求的那個點上5)不返回,直接呼叫abort或exit

相關推薦

C++ 處理new分配記憶體失敗

轉自:http://www.51testing.com/html/70/n-827070.html在C++語言中,我們經常會使用new給一個物件分配記憶體空間,而當記憶體不夠會出現記憶體不足的情況。C++提供了兩中報告方式:  1、丟擲bad_alloc異常來報告分配失敗; 

處理new分配記憶體失敗情況

轉自:http://www.51testing.com/html/70/n-827070.html 在C++語言中,我們經常會使用new給一個物件分配記憶體空間,而當記憶體不夠會出現記憶體不足的情況。C++提供了兩中報告方式:   1、丟擲bad_alloc異常來報告分配失敗;   2、返回空指標,而不

C++ Primer Plus書之--C++指標及使用new分配記憶體,使用delete釋放記憶體

先來個簡單的程式初步認識一下指標  #include "iostream" using namespace std; int main() { // 定義一個int型變數 int num = 123; // 定義一個int型指標變數 int * p_num; // 指標指向

C++學習10:使用new分配記憶體

在C++中,可以沿用C中的malloc分配記憶體,也可以使用new運算子。今天就來學習使用new分配記憶體。 new的作用和使用方法: new的作用在於可以在程式執行階段動態分配記憶體,記憶體的大小在執行時根據需要確定,從而高效利用記憶體空間。 new

c語言動態分配記憶體記憶體分配部分函式

#include<stdio.h> /** 在C中動態分配記憶體的基本步驟有: 1,用malloc類的函式分配記憶體; 2,用這些記憶體支援應用程式 3,用free函式釋放記憶體 二、動態記憶體分配函式     malloc :從堆上分配記憶體 &nbs

C語言--動態分配記憶體空間的使用方法

#include <stdio.h> #include <stdlib.h> int main() { int i; int *nums; //為指標分配動態的記憶體空間 // nums = (int *)mall

C語言:動態分配記憶體,malloc()與realloc()區別

#include <stdio.h> #include <stdlib.h> //動態分配記憶體標頭檔案 int main() { /* 何為動態?

使用new分配記憶體、建立動態陣列、

1、使用new來分配記憶體 程式設計師需要告訴new,需要為哪種資料型別分配記憶體;new將找到一個長度正確的記憶體塊,並返回該記憶體塊的地址, 程式設計師的責任是將改地址賦給一個指標。 int *pn = new int; new int告訴程式,需要儲存i

C++ placement new記憶體

有些時候我們需要能夠長時間執行的程式(例如監聽程式,伺服器程式)對於這些7*24執行的程式,我們不應該使用標準庫提供的new 和 delete (malloc和free也算)。這是因為隨著程式的執行,記憶體不斷的被申請和被釋放,頻繁的申請和釋放將會引發記憶體碎片、記憶體不足

C++new失敗處理(如果 new 分配內存失敗,默認是拋出異常的,但也可以取消異常)

影響 vc++ handler 出錯 for 有意義 全局 靈活性 arr 我們都知道,使用 malloc/calloc 等分配內存的函數時,一定要檢查其返回值是否為“空指針”(亦即檢查分配內存的操作是否成功),這是良好的編程習慣,也是編寫可靠程序所

C++ new動態分配記憶體和delete釋放記憶體

C++中使用簡便而強大的new和delete運算子來進行動態記憶體的分配. 值得注意的是,new和delete和c語言中的malloc和free不同,new和delete是運算子,因此執行效率更高. 如何使用new , delete 呢? 首先我們來看一段程式碼: i

C++動態分配記憶體空間 : new 和 delete

1.什麼是new和delete 在C語言中我們可以利用標準庫函式中的 malloc 和 free 來動態分配記憶體空間,而在C++中提供了運算子 new 和 delete 來取代 malloc 和 f

C++之 new 動態分配記憶體

動態記憶體分配 1.堆記憶體分配 : C/C++定義了4個記憶體區間:程式碼區,全域性變數與靜態變數區,區域性變數區即棧區,動態儲存區,即堆(heap)區或自由儲存區(free store)。 堆的概念: 通常定義變數(或物件),編譯器在編譯時都可以根據該變數(或物件)的

C++動態分配記憶體(new)和撤銷記憶體(delete)

在軟體開發過程中,常常需要動態地分配和撤銷記憶體空間,例如對動態連結串列中結點的插入與刪除。 在C語言中是利用庫函式malloc和free來分配和撤銷記憶體空間的。 C++提供了較簡便而功能較強的運算子new和delete來取代malloc和free函式。

C++的 new 代替 C 的 malloc 進行記憶體分配

例子: (int*)malloc(100*sizeof(int)) 是先取得int型別的位元組寬度,然後乘100計算後得到400,然後呼叫malloc,並將400傳遞給函式,分配400位元組的記憶體空間,但是返回的是虛指標,即純地址,該地址的型別是未知的,也即缺少資料寬度的

C++new動態分配記憶體生成陣列

#include <iostream> using namespace std; static int b[3][3]; void change(int (*a)[3])//轉置函式 { for(int m=0;m<3;m++) { for(int

C++中關於[]靜態數組和new分配的動態數組的區別分析

zid dad ima lin aer uem asa iba ash %E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E8%99%9A%E6%8B%9F%E6%9C%BA7---%E7%BA%BF%E7%A8%8B%E5%AE%89%E5

C++內存分配new和malloc的區別

href 構造函數 alloc 拋出異常 delete 錯誤 malloc all oid 這裏有一篇講的很詳細new和malloc的區別 總結一下: 1.new/delete是操作符,malloc/free是函數 2.malloc分配內存需指定大小,且只能是一般數據

C++操作符new-動態存儲空間分配

c++ 操作 動態 mil bsp ++操作 -s span new c++操作符new可以用來動態存儲分配,我簡單的對new的作用做了簡單的整理。 1.單個字符或整數 1 int *p=new int; 2 *p=10; 3

c語言獲得動態分配記憶體後的陣列記憶體大小

c語言獲得動態分配記憶體後的陣列記憶體大小 用一個函式 :_msize(); ★注意:該函式為Windows獨有★ int* s = (int*)malloc(sizeof(int));     int i;     for(i