C/C++ 內存分佈與管理

內存分佈
站在彙編語言的角度,一個程序分爲: 代碼段--CS   數據段--DS      堆棧段--SS     擴展段--ES
站在高級語言的角度,根據APUE,一個程序分爲如下段:text     data(initialized)  bss     heap    stack  ;
存儲時存在3個區域,分別是:代碼段、數據段以及BSS段;
當程序被加載到內存單元時(即運行,此時可稱之爲: 進程),則需要另外兩個區:堆和棧
在x86處理器上的Linux,代碼段從0x08048000單元開始,棧則從0xC0000000(棧底,高地址)往下(往低地址)增長。棧由棧幀組成,系統會爲每個當前調用的函數分配一個棧幀。棧幀中存儲了函數的局部變量、實參和返回值;
 
局部變量(static聲明的除外)
(注:函數形參屬於局部變量)
向下增長、先進後出
動態內存分配的
向上增長、先進先出
BSS 段
未初始化的全局變量、未初始化的靜態變量
在程序載入時由內核將此段中數據初始化爲0或空指針。
數據段
初始化的全局變量、初始化的靜態變量
、常量(注意包括字符串常量)
可讀可寫
代碼段
可執行代碼
此區域通常爲只讀
注:
1、全局變量不初始化,在運行時內核賦值爲0或NULL; 局部變量不初始化 值不定(不同編譯器有不同的值)
2、局部指針char *s = "abc";
//s爲局部變量,存儲在棧區,"abc"爲字符串常量,存儲在已初始化數據區,只讀!!!
指針變量和其他常見的(int、char)變量一樣,只不過它存的是地址而已,在內存中存放的位置和其他變量一樣的
 
 
 

字節轉換
            1 B/byte(字節) = 8 bit(比特)
2^10    1 KB(千字節) = 1024 B/byte(字節)
2^20    1 MB = 1024 KB
2^30    1 GB = 1024 MB
2^40    1 TB = 1024 GB
            1 PB = 1024 TB

例題
 
 
 
C語言內存分配函數(在堆區操作)
1、malloc函數:申請的是虛擬內存;
原型:void* malloc (size_t size);
Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.並不初始化,內存裏面的值爲隨機值;
例:p = (int*) malloc( sizeof(int) * 20 )
 
2、calloc函數
原型:void* calloc (size_t num, size_t size)
Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.
例:pData = (int*) calloc (20,sizeof(int));// 分配20個的數組分配內存塊,每個元素爲sizeof(int)大小,並均初始化爲0
 
3、realloc函數
原型:void* realloc (void* ptr, size_t size);
Changes the size of the memory block pointed to by ptr.重新調整ptr指向內存的大小,只可以擴大
 
4、free函數:釋放的也是虛擬內存;
原型:void free (void* ptr);
釋放prt所指的內存塊
 
 
 
 
C++ 內存分配函數
1、new / delete
定義1:int *p1 = new int(1024); // 初始值爲1024
       delete p1; 
        p1 = NULL;

vector<int> *pv = new vector<int> {0,1,2,3,4,5,6,7,8,9}; // 10個元素,0 - 9

string *ps = new string();// 默認初始化爲空串

int *pp = new int(); // 默認初始化爲0


定義2:int *p2 = new int; // p2指向一個動態分配的、未初始化的無名對象
        delete p2;

使用new分配cosnst 對象是合法的;const 對象必須進行初始化,
const int *p = new const int (5);

2、new[] / delete[]

定義1:int *p3 = new int[10] // 創建10個元素的數組
    delete[] p3;
    p3 = nullptr;
注:
1、對空指針使用delete不存在問題;
2、使用new [ ] 分配的內存應使用delete [ ] 來釋放;
3、不能對同一內存使用兩次delete;
 
 
 
 
野指針的成因
1、指針變量未初始化;
2、指針操作超出變量的作用域;
3、指針釋放之後未置空;
delete一個指針後,指針變成了空懸指針,即指向一塊曾經保存數據對象但現在已經無效的內存指針。
free/delete只是把指針所指的內存給釋放掉了,但並沒有把指針本身幹掉,它仍保存那個無效的地址,因此釋放完指針應立即將指針設置爲 NULL/nullptr。但這只是提供了有限的保護:看下例
    int *p = new int(502);
    int *q = p;
    
    delete p;
    p = nullptr;
p 和 q 指向相同的動態分配的對象,delete p所指的內存後置爲nullptr,但是 q 仍然指向剛剛釋放掉的內存,q 變爲無效在實際系統中,查找指向相同內存的所有指針是十分困難的。可以使用智能指針解決。
 
 
int main()
{
    int *p;// p沒有指向確定指針,隨機指向一個地址,十分的危險     
    printf("0x%x \n", p);
    *p = 5;
    printf("%d \n", *p); // 若無上句的賦值,將非法訪問內存,程序奔潰
    return 0;
}
 
 
malloc/free 和 new/delete 的區別
1、new/delete是操作符;而malloc/free函數,需要相關頭文件支持;
2、new/delete出分配/釋放內存外,還會調用構造函數/析構函數;而malloc/free僅僅只是分配/釋放內存;
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章