動態(tài)內存
1.內存泄漏
如果不再使用已分配的內存卻沒有將其釋放就會發(fā)生內存泄漏
- 丟失內存地址: 同一個指針被malloc()函數(shù)多次賦值導致之前的賦值的內存地址丟失; 指針賦值為null導致內存地址丟失
- 隱式內存泄漏
2.動態(tài)內存分配函數(shù)
//malloc函數(shù)原型
void* malloc(size_t);
//如果malloc的參數(shù)是0测蘑,其行為是實現(xiàn)相關的:可能返回NULL指針仿荆,也可能返回一個指向分配了0字節(jié)區(qū)域的指針山涡。
//如果malloc函數(shù)的參數(shù)是NULL,那么一般會生成一個警告然后返回0字節(jié)
//當malloc無法分配內存時會返回NULL昔头,在使用它返回的指針之前先檢查NULL是不錯的做法
int *pi = (int*) malloc(sizeof(int));
if(pi != NULL) {
// 指針沒有問題
} else {
//無效指針
}
//初始化靜態(tài)或全局變量時不能調用函數(shù)
static int *pi;
pi = malloc(sizeof(int));
//calloc在分配的同時清空內存將內容置為0
void *calloc(size_t numElements, size_t elementSize);
//用malloc函數(shù)和memset函數(shù)可以得到同樣的結果
/*
memset函數(shù)會用某個值填充內存塊涨薪。
第一個參數(shù)是指向要填充的緩沖區(qū)的指針辈赋,
第二個參數(shù)是填充緩沖區(qū)的值慌烧,
第三個參數(shù)是要填充的字節(jié)數(shù)
*/
int *pi = malloc(5 * sizeof(int));
memset(pi, 0, 5* sizeof(int))
//realloc函數(shù)會重新分配內存,第一個參數(shù)是指向原內存塊的指針逐抑,第二個是請求的大小
void *realloc(void *ptr, size_t size);
//free函數(shù)
void free(void *ptr);
3.迷途指針
指針指向的地址已被釋放,但指針仍在引用原始內存的指針,成為迷途指針
int *p1 = (int*) malloc(sizeof(int));
*p1 = 5;
int *p2;
p2 = p1;
free(p1);
//p1,p2成為迷途指針
int *pi;
...
{
int tmp = 5;
pi = &tmp;
}// 這里pi變成了迷途指針
foo();
//處理方法
//釋放指針后置為NULL,后續(xù)使用這個指針會終止程序.
//有些系統(tǒng)(運行時或調試系統(tǒng))會在釋放后覆寫數(shù)據.在不拋出異常的情況下,如果程序員在預期之外的地方看到這些值屹蚊,可以認為程序可能在訪問已釋放的內存
//用第三方工具檢測迷途指針和其他問題
4.垃圾回收
資源獲取即初始化(Resource Acquisition Is Initialization厕氨,RAII): 即使有異常發(fā)生,這種技術也能保證資源的初始化和后續(xù)的釋放汹粤。分配的資源最終總是會得到釋放
-
異常處理函數(shù): try塊包含任何可能在運行時拋出異常的語句腐巢。不管有沒有異常拋出,都會執(zhí)行finally塊玄括,因此也一定會執(zhí)行free函數(shù)
void exceptionExample() { int *pi = NULL; __try { pi = (int*)malloc(sizeof(int)); *pi = 5; printf("%d\n",*pi); } __finally { free(pi); }