JNI基礎之C動態記憶體分配筆記
當我們在執行下面一段程式碼時,會丟擲stack overflow的異常:
#include <stdio.h>
void main(){
int i[1024 * 1024 * 10];
getchar();
}
這個錯誤直譯過來就是棧溢位,這裡面就涉及到C語言的記憶體區域的分配問題。
C語言記憶體區域劃分
1、棧區(stack) 先進後出的記憶體結構,所有的自動變數、函式形參都儲存在棧中
每個執行緒都有自己的棧幀
棧記憶體尺寸固定,超過則引起棧溢位,如上面的程式碼:
自動分配(申請方式如:int i[10];),變數離開作用域後自動釋放
2、堆區 (heap) 和棧一樣,也是一種在程式執行過程中可以隨時修改的記憶體區域,但沒有棧那樣先進後出的順序
- 申請方式: int *p = malloc(1024);
由程式設計師手動分配和釋放,
- 可分配約佔作業系統80%記憶體
3、全域性、靜態區
靜態區存放程式中所有的全域性變數和靜態變數。
4、字元常量區
常量字串就是放在這裡的。 程式結束後由系統釋放
5、程式程式碼區
程式被作業系統載入到記憶體的時候,所有的可執行程式碼(程式程式碼指令、常量字串等)都載入到程式碼區
這塊記憶體在程式執行期間是不變的。
程式碼區是平行的,裡面裝的就是一堆指令,在程式執行期間是不能改變的。
動態分配記憶體
1、malloc函式:向堆申請開啟指定大小的記憶體區域
//分配40M記憶體
int* p = malloc(1024 * 1024 * 10 * sizeof(int));
2、realloc()函式:調整已分配的記憶體區域
//
int* p = malloc(100 * sizeof(int));
//發現記憶體不夠用,重新分配記憶體;
int* p2 = realloc(p, sizeof(int) * 200);
3、free()函式:釋放已分配的記憶體區域;
//開闢40M記憶體
int* p = malloc(1024 * 1024 * 10 * sizeof(int));
//釋放
free(p)
區別:
靜態記憶體分配建立陣列,陣列大小固定,必須在指定陣列長度。
int i[3];
int ids[] = {10, 20, 22};
動態記憶體分配建立陣列,開闢一段記憶體,然後在這段記憶體上賦值陣列,在程式執行過程中,可以隨意的開闢指定大小的記憶體以供使用,相當於java中的集合。
int len = 1024; //指標長度
//開闢記憶體,1024*4個位元組
int *p = malloc(len * sizeof(int));
int i = 0;
//給陣列賦值
for(; i < len; i++){
p[i] = rand();
}
靜態記憶體分配,記憶體分配的大小是固定的,有以下問題
- 容易超出棧記憶體的最大值;
- 通常為了防止記憶體不夠用,會開闢更多地記憶體,容易造成記憶體浪費
動態記憶體分配,在程式執行過程中動態指定需要使用的記憶體大小,手動釋放,釋放後這些記憶體還可以被重新利用。同時可以重新分配記憶體區域的大小
關於realloc重新分配記憶體:
1、縮小記憶體,即分配後的記憶體區域大小比原來的記憶體區域要小,則直接截去多餘的記憶體,返回的指標和原來的指標指向 地址相同,返回原指標。
2、擴大記憶體:即分配後的記憶體區域要大於原記憶體大小。
(1)因為分配的記憶體是連續的,若當前指標後的記憶體區域後續記憶體端足夠分配,則直接在後續的記憶體區域分配給當前指標,返回原指標。
(2)若當前指標後續記憶體區域不足以分配,則使用堆中第一塊滿足這一條件的記憶體塊,並把當前的資料複製到新的記憶體塊中,返回新的指向改記憶體塊的指標,原記憶體塊被釋放。
(3)堆中記憶體不足,申請失敗,返回NULL,原來的指標仍有效;
記憶體分配的幾個注意事項
- 記憶體不能重複釋放,所以一般在釋放前做一個NULL判斷:
- 養成一個良好習慣,在釋放掉一個記憶體後,並置為空NULL;
if( p != NULL){ free(p); //可以看到p仍有值 printf("%#x\n", p); p = NULL; }
- 重複給一個變數呼叫malloc函式,要在合適的時機呼叫free,否則造成記憶體洩漏
//第一次分配記憶體 int *p = malloc(1024 * 10 * sizeof(int)); //第二次分配記憶體 p = malloc(1024 * 4 * sizeof(int)); //釋放記憶體 free(p);
這裡調了一次free釋放記憶體,然而呼叫了兩次記憶體分配開闢了兩段記憶體區域,第一次p指向了第一段記憶體區域,第二次指向了新分配的記憶體區域,呼叫了free釋放的是第二段記憶體,則第一段記憶體仍沒有得到釋放,從而造成記憶體洩漏