1.
內(nèi)存分配未成功,卻使用了它。
如果指針
P
是函數(shù)的參數(shù),那么在函數(shù)的入口處用
assert(p
!=
NULL)
進(jìn)行檢查。如果是用
malloc
或
new
來申請(qǐng)內(nèi)存,應(yīng)該用
if(p
==
NULL)
或者
if(P != NULL)
來進(jìn)行防錯(cuò)處理。
2.
內(nèi)存分配雖然成功,但是尚未初始化就引用它。
(犯錯(cuò)的原因:
1.
沒有初始化的觀念;
誤以為內(nèi)存的缺省初值全為
0
,導(dǎo)致引用初值的錯(cuò)誤(如數(shù)組)
)
。
3.
內(nèi)存分配成功并且已經(jīng)初始化,但操作越過了內(nèi)存的邊界。
(數(shù)據(jù)下標(biāo)發(fā)生“多
1
”或
者“少
1
”的操作。特別是在
for
循環(huán)語句中,循環(huán)次數(shù)很容易搞錯(cuò),導(dǎo)致數(shù)組越界)
。
4.
忘記了釋放內(nèi)存,造成內(nèi)存泄漏。
(含這種錯(cuò)誤的函數(shù)每次調(diào)用就丟失一塊內(nèi)存。剛剛
開始系統(tǒng)的內(nèi)存充足,
可能看不到。
但程序突然有一次死掉,
系統(tǒng)出現(xiàn)提示:
內(nèi)存耗盡)
動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),程序中
malloc
與
free
的使用次數(shù)一定要相同,否則
肯定有錯(cuò)誤
(new/delete
同理
)
5.
釋放了內(nèi)存卻繼續(xù)使用它。
一:
程序中的對(duì)象調(diào)用關(guān)系過于復(fù)雜,
實(shí)在難以搞清楚某個(gè)
對(duì)象究竟是否已經(jīng)釋放了內(nèi)存,
此時(shí)應(yīng)該重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),
從根本上解決對(duì)象管理混
亂局面。二:函數(shù)
return
語句寫錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者
引用,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。三、使用
free
或
delete
釋放內(nèi)存后,
沒有將指針設(shè)置為
NULL
,導(dǎo)致產(chǎn)生“野指針”
。
規(guī)則:
用
malloc
或
new
申請(qǐng)內(nèi)存后,
應(yīng)該立即檢查指針是否為
NULL
,
防止使用指針值為
NULL
的內(nèi)存。
不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用。
避免數(shù)組或者指針下標(biāo)越界,特別當(dāng)心發(fā)生“多
1
”或者“少
1
“
動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),防止內(nèi)存泄漏。
用
free
或
delete
釋放了內(nèi)存之后,立即將指針設(shè)置為
NULL
,防止產(chǎn)生“野指針”
。
數(shù)組和指針之間區(qū)別:
1.
修改內(nèi)容。
Char a[] =
“
hello
”
A[0] =
‘
X0
’
Cout
<< a << endl //
可以改變常量的值。
Char *p =
“
world
”
//P
是指向常量的字符串,
。
P[0] =
‘
X
’
//error,
指針
P
指向常量字符串
”
world
,常量字符串的內(nèi)容是不可被修改
的
”
2.
內(nèi)容復(fù)制與比較。
數(shù)組的復(fù)制:
Char a[] =
“
hello
”
Char b[10]
Strcpy(b, a);
If (strcmp(b,a) == 0)
指針
Int
len = strlen(a);
Char *p = (char *)malloc(sizeof(char) * (len + 1))
If(NULL == p)
Return
-1
Strcpy(p,a)
//
If(strcmpy(p,a) == 0)
3.
指針參數(shù)如何傳遞內(nèi)存。
Y
:
Void GetMemory1(char *p, int num)
{
P = (char *)malloc(sizeof(char) * num)
}
//
問題:
編譯器總是要為函數(shù)的每個(gè)參數(shù)制作臨時(shí)副本,
指針參數(shù)
p
的副本上
_p,
編譯器使
_p = p .
如果函數(shù)體內(nèi)的程序修改了
_p
的內(nèi)容
,
就導(dǎo)致參數(shù)
P
的內(nèi)容作
相應(yīng)的修改
。這就是指針可以用作輸出參數(shù)的原因。在本例中,
_p
申請(qǐng)了新的內(nèi)
存,
只是把
_p
所指的內(nèi)存地址改變了,但是
p
絲毫未變
。所以函數(shù)
GetMemory
并
不能輸出任何東西,事實(shí)上,每執(zhí)行一次
GetMemory
就會(huì)泄漏一塊內(nèi)存,因?yàn)闆]
有用
free
釋放內(nèi)存。
用指向指針的指針后解決這個(gè)問題:
Void GetMemory2(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num)
}
用函數(shù)返回值了解決:
Char *GetMemory3(int num)
{
Char *p = (cahr * )malloc(sizeof(char) * num)
Return p
}
Void Test(void)
{
Char *str = NULL
GetMemory1(str, 100);//
申請(qǐng)內(nèi)存錯(cuò)誤
GetMemory2(&str, 100) //
注意參數(shù)是
&str
,而不是
str
。
Str = GetMemory3(100)
Strcpy(str,
“
hello
”
);
}
4.
Free/delete,
只是把指針?biāo)傅膬?nèi)存釋放掉,并沒有把指針本身干掉。
5.
函數(shù)體內(nèi)局部變量在函數(shù)結(jié)束時(shí)自動(dòng)消亡。
但是局部指針變量,
消亡的時(shí)候它所指
的動(dòng)態(tài)內(nèi)存不一定一起消亡
.(
比如別的模塊調(diào)用怎么辦
)
。
1
、指針消亡了,并不表
示它所指的內(nèi)存會(huì)被自動(dòng)釋放。
2
、內(nèi)存被釋放了,并不表示指針會(huì)消亡或者成了
NULL
指針。
6.
野指針,不是
NULL
指針,是指向“垃圾”內(nèi)存的指針。形成的原因:
1
、指針變
量沒有被初始化。任何指針變量剛剛被創(chuàng)建時(shí)不會(huì)自動(dòng)成為
NULL
指針,它的缺省
值是隨機(jī)的,
它會(huì)亂指一起。
所以,
指針變量在創(chuàng)建的同時(shí)應(yīng)當(dāng)被初始化,
要么將
指針設(shè)置為
NULL
,要么讓它指向合法的內(nèi)存。
Char *p = NULL char *str =(char
*)malloc(100) 2
、指針
P
被
free/delete
之后,沒有被指為
NULL
,讓人誤認(rèn)為
P
是
合法的指針。
3.
指針操作超越了變量的作用范圍。
7.
MAlloc
與
free
是
C/C++
語言的標(biāo)準(zhǔn)庫函數(shù),
new/delete
是
C++
的運(yùn)算符,它們都是
可以用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。
對(duì)于非內(nèi)部數(shù)據(jù)類型的對(duì)象而言,光
malloc
和
free
無法滿足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對(duì)象
在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由于
malloc/free
是庫函數(shù)而不是運(yùn)算符,不再
編譯器控制的權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加與
malloc/free
。
不要企圖用
malloc/free
來完成動(dòng)態(tài)對(duì)象的內(nèi)存管理,
應(yīng)該用
new/delete.
由于內(nèi)部數(shù)據(jù)類型的
”
對(duì)象
”
沒有構(gòu)造與析構(gòu)的過程,對(duì)他們而言
malloc/free
,
new/delete
是等價(jià)的。
New/delete
的功能完全覆蓋了
malloc/free
的功能,保留的
原因是
C++
經(jīng)常需要調(diào)用
C
函數(shù),
而
c
程序只能用
malloc/free
動(dòng)態(tài)管理內(nèi)存。
如果
用
free
釋放“
new
創(chuàng)建的動(dòng)態(tài)對(duì)象”
,那么該對(duì)象因無法執(zhí)行析構(gòu)函數(shù)而可能導(dǎo)致
程序出錯(cuò)。
8.
內(nèi)存申請(qǐng)不到。
1
、
判斷指針是否為
NULL
,
如果是則馬上用
return
語句終止本函數(shù)。
Void Func(void)
{
A
*a = new A
If(NULL == a)
{
Return
}
…
.
}
B
.判斷指針是否為
NULL
,如果是則馬上用
exit(1)
終止整個(gè)程序的運(yùn)行。
Void func(void)
{
A *a = new A
If (NULL == a)
{
cout <<
“
memory Exhausted
”
<<endl
Exit(1)
}
}
C:
為
new
和
malloc
設(shè)置異常處理函數(shù)。
1.
Malloc /free
的使用要點(diǎn)
函數(shù)原型:
void *malloc(size_t size) //
用
malloc
申請(qǐng)一塊長(zhǎng)度為
length
的整數(shù)
類型的內(nèi)存。
Int *p = (int *) malloc(sizeof(int) *length)
A:malloc
返回值的類型是
void * ,
所以在調(diào)用
malloc
時(shí)要顯式地進(jìn)行類型轉(zhuǎn)換,
將
void*
轉(zhuǎn)換成所需的指針類型。
B:malloc
函數(shù)本身并不知道申請(qǐng)內(nèi)存是什么類型,只關(guān)心內(nèi)存自己總數(shù)。
2.
函數(shù)
free
的原型如下:
void free(void *memblock)
指針
p
的類型以及指向的內(nèi)
存容量事先都知道,所以
free(p)
能正確釋放內(nèi)存。如果
P
是
NULL
指針,那么
free
對(duì)
P
無論操作多少次都不會(huì)出現(xiàn)問題,如果
P
不是
NULL
指針,那么
free
對(duì)
P
連續(xù)操作兩次就會(huì)導(dǎo)致程序運(yùn)行出錯(cuò)。
3.
New/delete
要點(diǎn)。
Int *p2 = new int[length]
因?yàn)?div style="height:15px;">
1.
1.
2.