內(nèi)存分配方式有三種:
1.從靜態(tài)存儲(chǔ)區(qū)域分配。在程序編譯的時(shí)候就分配好了內(nèi)存,這個(gè)內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。
例如 全局變量,static變量。
2.在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。
效率比較高,但是分配的內(nèi)存容量有限。
3.從堆上分配,即動(dòng)態(tài)內(nèi)存分配。用malloc或new申請(qǐng)任意多少的內(nèi)存。用free或delete釋放內(nèi)存。
常見的內(nèi)存錯(cuò)誤:
1.內(nèi)存分配未成功,卻使用了它。
如果指針P是函數(shù)的參數(shù) 那么在函數(shù)的入口處用assert(p!=null)進(jìn)行檢查。
如果用malloc或者new來申請(qǐng)內(nèi)存,用if(p==null) 或 if(p!=null)來進(jìn)行防錯(cuò)處理。
2.內(nèi)存分配成功,但是尚未初始化就引用它。
無論以何種方式創(chuàng)建數(shù)組,被忘了賦初值。
char *p = malloc(10);
memset(p,'\0',10);
3.內(nèi)存分配成功并且已經(jīng)初始化,但是內(nèi)存越界了。
char *ptr = (char *) malloc(10)
char name[20]
memcpy(name,ptr,20)
4.忘記了釋放內(nèi)存,造成內(nèi)存泄露。
5.釋放了內(nèi)存,卻還在使用它。
a).返回的是“棧內(nèi)存”的指針,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。
b).使用free或者delete釋放內(nèi)存后,沒有將指針設(shè)置為NULL,導(dǎo)致“野指針”。
錯(cuò)誤范例:
1.void GetMemmory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL; //申請(qǐng)一個(gè)char類型的指針str,并把str指向NULL(即str里存的是NULL的地址,*str為NULL中的值為0),
GetMemmory(str);
strcpy(str,"hello world");
printf(str);
}
2.char *GetMemory(void)
{
char p[] = "hello world" ; //此行將p[]改成*p就對(duì)了,此時(shí)p[]存在于棧里邊,*p的話字符串存于常量區(qū)
return p; //return數(shù)組名后,會(huì)釋放掉它里面所有的變量所占用的空間,所以數(shù)組空間被釋放掉了.
}
void Test(void)
{
char *str =NULL;
str = GetMemory();
printf(str);
}
3.void GetMemory2(char **p, int num)
{ *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str,100); strcpy(str,hello); printf(str); } 4.void Test(void)
{ char *str = (char *)malloc(100); strcpy(str,hello); free(str); if(str != NULL) //一個(gè)指針被釋放之后其內(nèi)容并不是NULL,而是一個(gè)不確定的值 { strcpy(str,world); printf(str); } } |
|