C++中的内存管理(new、delete、内存泄漏)
生活随笔
收集整理的這篇文章主要介紹了
C++中的内存管理(new、delete、内存泄漏)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 使用new動態分配內存:若沒有足夠內存,則new返回0(空值指針null pointer);
2. 不要使用delete釋放不是new分配的內存,delete釋放指針指向的內存,但不會刪除指針本身;
3、對空值指針應用delete是安全的;
4、創建數組時的靜態聯編與動態聯編:數組聲名int a[10], 靜態聯編,數組的長度在編譯時確定;
???? 用new[]創建數組,動態聯編,運行時為數組分配內存空間。動態-運行時分配內存。
C++有3種管理數據內存的方式:自動存儲、靜態存儲、動態存儲(自由存儲空間或堆)(三塊獨立的內存)
自動存儲:(auto /? register ) 自動變量的持久性為自動的,在程序開始執行其所屬的函數或代碼塊時創建,執行???????????????????完后釋放。
? ? ? ? ? ? ? ? ? ?? auto: in stack LIFO?
????????????????????register: in CPU register,使用寄存器處理變量,提高訪問速度;沒有內存地址,不能用&取地址。
靜態存儲:(global / static ) 在程序整個運行期間都存在. (外部鏈接性、內部鏈接性、無鏈接性)
??????????????????? 初始化為0。
? ?? int? global = 1000;? //外部鏈接性,可在程序的其他文件使用, 使用時要用extern聲名? (外部變量/全局變量)
??? static int one_file = 50; //內部鏈接性,只能在本文件使用?? (函數如果為static也一樣,只能在該文件中被調)
??? int main(){????? ...? }
??? void func(){
??? ???? static int count = 0;? //靜態局部變量,只在該代碼中可用,但它在該代碼不活動時始終存在。
?? }
??? 可用extern重新聲名以前定義過的外部變量;
??? 訪問被隱藏的外部變量(被局部變量隱藏了):用作用域解析符(::)::n 表示使用n的全局版本
?? const char * const months[12] = {"Jan", "Feb", "Mar",...};
?//第一個const防止字符串被修改,第二個const確保數組中每個指針始終指向它最初指向的字符串。
??? mutable限定符:const/volatile/mutable? const禁止修改結構成員,但是mutable使const結構中的成員不受這種限制
???? struct data { char name[30];? mutable int accesses;? };
???? const data? a = {....};??strcpy(a.name, "fdsf"); //not allowed????a.access++//allowed
???? 外部定義的const數據的鏈接性為內部的,跟static一樣
動態存儲:(free store / heap)? new/delete,? malloc/free
? 1、使用new來設置指針的語句必須位于函數中,因為只能使用常量表達式來初始化靜態存儲變量:
?????? float * p;
?????? //float *p = new float[20]; //initialization with non-const not allowed here
??????? main (){?? p = new float[20];? }
?? 2、布局new操作符 (placement new): 自己指定空間為placement new提供內存空間,而不是在heap中分配
????? #include<new>
????? char buffer[512];
?????? ......double *pd1, *pd2;
???????????? pd1 = new double[N];
???????????? pd2 = new (buffer) double[N];
注:不能用delete [] pd2; 來釋放分配的內存,buffer指向的內存是靜態的,delete只能用于指向常規new分配的堆??????? 內存(free store)
??????
內存泄漏(memory leak)- 被分配的內存再也不能使用了,也無法回收
?????????????????????????????????????????????(new和delete使用不恰當,沒有配對使用而產生)
?????? 如果使用new操作符在自由存儲空間上創建變量后,沒有調用delete,則即使包含指針的內存
由于作用域和對象生命周期的原因而被釋放,在自由存儲區動態分配的變量或結構也將繼續存在,
這樣,將無法訪問free store空間中的結構,因為指向這些內存的指針無效,因此這些被分配的內存
將無法使用,從而導致內存泄漏。
一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完后必須顯示釋放的內存。應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完后,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了
檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數的調用。截獲住這兩個函數,我們就能跟蹤每一塊內存的生命周期,比如,每當成功的分配一塊內存后,就把它的指針加入一個全局的list中;每當釋放一塊內存,再把它的指針從list中刪除。這樣,當程序結束的時候,list中剩余的指針就是指向那些沒有被釋放的內存。這里只是簡單的描述了檢測內存泄漏的基本原理,詳細的算法可以參見Steve Maguire的<<WritingSolid Code>>。
如果要檢測堆內存的泄漏,那么需要截獲住malloc/realloc/free和new/delete就可以了(其實new/delete最終也是用malloc/free的,所以只要截獲前面一組即可)。對于其他的泄漏,可以采用類似的方法,截獲住相應的分配和釋放函數。比如,要檢測BSTR的泄漏,就需要截獲SysAllocString/SysFreeString;要檢測HMENU的泄漏,就需要截獲CreateMenu/DestroyMenu。(有的資源的分配函數有多個,釋放函數只有一個,比如,SysAllocStringLen也可以用來分配BSTR,這時就需要截獲多個分配函數)
2. 不要使用delete釋放不是new分配的內存,delete釋放指針指向的內存,但不會刪除指針本身;
3、對空值指針應用delete是安全的;
4、創建數組時的靜態聯編與動態聯編:數組聲名int a[10], 靜態聯編,數組的長度在編譯時確定;
???? 用new[]創建數組,動態聯編,運行時為數組分配內存空間。動態-運行時分配內存。
C++有3種管理數據內存的方式:自動存儲、靜態存儲、動態存儲(自由存儲空間或堆)(三塊獨立的內存)
自動存儲:(auto /? register ) 自動變量的持久性為自動的,在程序開始執行其所屬的函數或代碼塊時創建,執行???????????????????完后釋放。
? ? ? ? ? ? ? ? ? ?? auto: in stack LIFO?
????????????????????register: in CPU register,使用寄存器處理變量,提高訪問速度;沒有內存地址,不能用&取地址。
靜態存儲:(global / static ) 在程序整個運行期間都存在. (外部鏈接性、內部鏈接性、無鏈接性)
??????????????????? 初始化為0。
? ?? int? global = 1000;? //外部鏈接性,可在程序的其他文件使用, 使用時要用extern聲名? (外部變量/全局變量)
??? static int one_file = 50; //內部鏈接性,只能在本文件使用?? (函數如果為static也一樣,只能在該文件中被調)
??? int main(){????? ...? }
??? void func(){
??? ???? static int count = 0;? //靜態局部變量,只在該代碼中可用,但它在該代碼不活動時始終存在。
?? }
??? 可用extern重新聲名以前定義過的外部變量;
??? 訪問被隱藏的外部變量(被局部變量隱藏了):用作用域解析符(::)::n 表示使用n的全局版本
?? const char * const months[12] = {"Jan", "Feb", "Mar",...};
?//第一個const防止字符串被修改,第二個const確保數組中每個指針始終指向它最初指向的字符串。
??? mutable限定符:const/volatile/mutable? const禁止修改結構成員,但是mutable使const結構中的成員不受這種限制
???? struct data { char name[30];? mutable int accesses;? };
???? const data? a = {....};??strcpy(a.name, "fdsf"); //not allowed????a.access++//allowed
???? 外部定義的const數據的鏈接性為內部的,跟static一樣
動態存儲:(free store / heap)? new/delete,? malloc/free
? 1、使用new來設置指針的語句必須位于函數中,因為只能使用常量表達式來初始化靜態存儲變量:
?????? float * p;
?????? //float *p = new float[20]; //initialization with non-const not allowed here
??????? main (){?? p = new float[20];? }
?? 2、布局new操作符 (placement new): 自己指定空間為placement new提供內存空間,而不是在heap中分配
????? #include<new>
????? char buffer[512];
?????? ......double *pd1, *pd2;
???????????? pd1 = new double[N];
???????????? pd2 = new (buffer) double[N];
注:不能用delete [] pd2; 來釋放分配的內存,buffer指向的內存是靜態的,delete只能用于指向常規new分配的堆??????? 內存(free store)
??????
內存泄漏(memory leak)- 被分配的內存再也不能使用了,也無法回收
?????????????????????????????????????????????(new和delete使用不恰當,沒有配對使用而產生)
?????? 如果使用new操作符在自由存儲空間上創建變量后,沒有調用delete,則即使包含指針的內存
由于作用域和對象生命周期的原因而被釋放,在自由存儲區動態分配的變量或結構也將繼續存在,
這樣,將無法訪問free store空間中的結構,因為指向這些內存的指針無效,因此這些被分配的內存
將無法使用,從而導致內存泄漏。
一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完后必須顯示釋放的內存。應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完后,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了
檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數的調用。截獲住這兩個函數,我們就能跟蹤每一塊內存的生命周期,比如,每當成功的分配一塊內存后,就把它的指針加入一個全局的list中;每當釋放一塊內存,再把它的指針從list中刪除。這樣,當程序結束的時候,list中剩余的指針就是指向那些沒有被釋放的內存。這里只是簡單的描述了檢測內存泄漏的基本原理,詳細的算法可以參見Steve Maguire的<<WritingSolid Code>>。
如果要檢測堆內存的泄漏,那么需要截獲住malloc/realloc/free和new/delete就可以了(其實new/delete最終也是用malloc/free的,所以只要截獲前面一組即可)。對于其他的泄漏,可以采用類似的方法,截獲住相應的分配和釋放函數。比如,要檢測BSTR的泄漏,就需要截獲SysAllocString/SysFreeString;要檢測HMENU的泄漏,就需要截獲CreateMenu/DestroyMenu。(有的資源的分配函數有多個,釋放函數只有一個,比如,SysAllocStringLen也可以用來分配BSTR,這時就需要截獲多個分配函數)
總結
以上是生活随笔為你收集整理的C++中的内存管理(new、delete、内存泄漏)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全局静态存储区、堆区和栈区深入剖析
- 下一篇: C++内存管理详解