?? c-c++實戰之內存管理 - rnarldo的個人空間 - linux寶庫 - powered by x-space.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<!-- saved from url=(0048)http://www.linuxpk.com/27039/viewspace-7997.html -->
<HTML xmlns="http://www.w3.org/1999/xhtml"><HEAD><TITLE>C/C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gbk">
<META content="工作 " name=keywords>
<META
content="歡迎大家來到這片大多數程序員都心有余悸的雷區。本世紀偉大的比爾·蓋茨曾經失言:640Koughttobeenoughforeverybody--BillGates1981相信程序員們都經常要編寫一些關于內存分配和使用的程序,而且都有過那種生不如. "
name=description><LINK title=rnarldo的個人空間
href="http://www.linuxpk.com/27039/action-rss-type-blog.html"
type=application/rss+xml rel=alternate><LINK title=RSD
href="http://www.linuxpk.com/xmlrpc.php?rsd=27039" type=application/rsd+xml
rel=EditURI><LINK id=commonstyle
href="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/space.css"
type=text/css rel=stylesheet><LINK id=themestyle
href="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/css_27039.cache.css"
type=text/css rel=stylesheet>
<SCRIPT type=text/javascript>
var siteUrl = "http://www.linuxpk.com";
</SCRIPT>
<SCRIPT language=javascript
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/ajax.js"
type=text/javascript></SCRIPT>
<SCRIPT language=javascript
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/common.js"
type=text/javascript></SCRIPT>
<META content="MSHTML 6.00.2800.1528" name=GENERATOR></HEAD>
<BODY>
<DIV id=wrap>
<DIV id=header>
<DIV id=spacename>
<DIV id=xspace-spacename><STRONG>rnarldo的個人空間</STRONG>
<P><A class=xspace-copyurl title=復制地址
onclick="javascript:setCopy('http://www.linuxpk.com/27039');"
href="javascript:;">copy</A> <A class=xspace-add2fav title=加入收藏
onclick="javascript:addBookmark('rnarldo的個人空間','http://www.linuxpk.com/27039');return false;"
href="http://www.linuxpk.com/27039">Bookmark</A> http://www.linuxpk.com/27039
</P></DIV></DIV>
<DIV id=menu>
<UL id=xspace-menu>
<LI class=xspace-active><A class=xspace-blog
href="http://www.linuxpk.com/27039/spacelist-blog.html">博客</A> </LI>
<LI><A class=xspace-image
href="http://www.linuxpk.com/27039/spacelist-image.html">圖片</A> </LI>
<LI><A class=xspace-friend
href="http://www.linuxpk.com/27039/spacelist-friend.html">好友</A> </LI>
<LI><A class=xspace-mybbs
href="http://www.linuxpk.com/27039/spacelist-bbs.html">論壇</A> </LI>
<LI><A class=xspace-guestbook
href="http://www.linuxpk.com/27039/action-viewpro.html">留言</A>
</LI></UL></DIV></DIV>
<DIV class=xspace-layout1 id=content>
<DIV class=mainarea-side id=mainarea>
<DIV id=xspace-guide><A class=xspace-spacecp
href="http://www.linuxpk.com/batch.manage.php?uid=27039" target=_blank>空間管理</A>
您的位置: <A href="http://www.linuxpk.com/" target=_blank>Linux寶庫</A> » <A
href="http://www.linuxpk.com/27039/">rnarldo的個人空間</A> » <A
href="http://www.linuxpk.com/27039/spacelist-blog.html">日志</A> </DIV>
<DIV id=show>
<H1 class=xspace-title>C/C++實戰之內存管理</H1>
<P class=xspace-smalltxt><A
href="http://www.linuxpk.com/batch.common.php?action=viewspace&op=up&itemid=7997&uid=27039">上一篇</A>
/ <A
href="http://www.linuxpk.com/batch.common.php?action=viewspace&op=next&itemid=7997&uid=27039">下一篇</A>
2007-11-22 15:38:45 / 個人分類:<A
href="http://www.linuxpk.com/27039/spacelist-blog-itemtypeid-996.html">C/C++</A>
</P>
<DIV class=xspace-itemdata><A
href="http://www.linuxpk.com/27039/viewspace-7997.html#xspace-tracks">查看( 60
)</A> / <A
href="http://www.linuxpk.com/27039/viewspace-7997.html#xspace-itemreply">評論( 0
)</A> / <A
href="http://www.linuxpk.com/27039/viewspace-7997.html#xspace-itemform">評分(
<SPAN class=xspace-rategood title=好評>0</SPAN> / <SPAN class=xspace-ratebad
title=差評>0</SPAN> )</A> </DIV>
<DIV class=xspace-itemmessage id=xspace-showmessage>
<DIV><FONT
size=3>歡迎大家來到這片大多數程序員都心有余悸的雷區。本世紀偉大的比爾·蓋茨曾經失言: <BR>640K ought to be enough for everybody -- Bill Gates 1981<BR></FONT></DIV>
<DIV><FONT
size=3>相信程序員們都經常要編寫一些關于內存分配和使用的程序,而且都有過那種生不如死的感覺(當然我是指那種調試程序的感覺了,可能夸張了些!)</FONT></DIV>
<DIV><FONT size=3><BR><FONT color=#0000ff>常見的內存分配和使用錯誤</FONT><BR>1)<FONT
color=#ff0000>內存的申請和分配并沒有成功,但程序員卻使用了它</FONT>。一些新手經常會犯這種錯誤,他們并不會留意到內存沒有分配成功。判斷指針的值是否為NULL可以有效地避免這種錯誤。<BR> <BR>2)<FONT
color=#ff0000>內存的分配已經成功,但是卻沒有進行初始化就直接使用它了</FONT>。首先是觀念上的問題,很多人都沒有在使用指針前要初始化這樣的習慣,然而這個習慣卻是很重要的,希望大家一定要強迫自己養成。第二就是主觀地認為自己申請的內存的缺省值為0,這樣想<BR>是沒有什么道理的,內存分配后的值是不確定的。
<BR> <BR>3)<FONT
color=#ff0000>上面的兩種工作都已經做好了(已經成功申請并初始化完成),但是操作時卻越界了</FONT>。<BR> <BR>4)<FONT
color=#ff0000>申請了內存,使用完了卻忘記了釋放,導致內存泄露</FONT>。這樣的錯誤可以形容為一個惡性的腫瘤,它不會馬上要你的命,但是它會慢慢地吞噬你的系統資源,直到你的程序徹底完蛋。
<BR> <BR>5)<FONT
color=#ff0000>你很小心地釋放了內存,但是卻又使用了它</FONT>。由于程序很復雜或者調用順序出錯,這樣可能導致出現上面的錯誤。 <BR><BR><FONT
color=#0000ff>指針---一把偉大的雙刃劍</FONT><BR><BR>我真的非常佩服發明指針的人,他簡直太偉大了。能使用如此簡潔地方法將復雜的內存結構描述的如此清楚,這本身就是一種偉大的成就。但是,指針之于程序員如同武器之于士兵,用好了可以威力無比,用不好則害人害己。<BR> <BR>我先說說指針和數組的區別。數組名對應著一塊內存,它的地址、容量在其生命周期中是不可變的,只有數組內容是可變的。指針可隨時指向任何類型的內存,它的特點就是“變”。指針遠比數組靈活,但也更危險。<FONT
color=#ff0000>數組名是不能直接進行賦值和比較的</FONT>。如果你向要將數組a賦值給數組b,不能直接用賦值語句b = a ,這樣會令編譯器產生錯誤的。<FONT
color=#ff0000>必須使用標準的庫函數strcpy來進行賦值</FONT>。相同地,要比較a和b的內容是否相同,不能使用普通的邏輯判斷if(b==a),<FONT
color=#ff0000>也要應用庫函數strcmp來判斷</FONT>。 <BR> <BR>//數組……
<BR> <BR>char a[] = “hello”;
<BR> <BR>char b[100];
<BR> <BR>strcpy(b, a); // b = a is wrong
<BR> <BR>if (strcmp(b, a) == 0) //if (b == a) is wrong
<BR> <BR> cout<<b<<endl;
<BR> <BR>//指針……
<BR> <BR>int len = strlen(a);
<BR> <BR>char *p = (char *)malloc(sizeof(char)*(len+1));
<BR> <BR>strcpy(p, a);
<BR> <BR>if (strcmp(p, a) == 0)
<BR> <BR> cout<<p<<endl;
<BR> <BR>free(p); <BR> <BR>在計算內存容量的時候有一點是必須要指出的,那就是<FONT
color=#ff0000>sizeof計算數組是計算它的實際的內存容量,而計算指針時則永遠都是4個字節</FONT>。C++是永遠沒有辦法知道指針所指的內存容量,除非在申請時記住它。 <BR><BR><FONT
color=#0000ff>free和delete如何對付指針?</FONT><BR><BR>程序員都知道它們是用來釋放申請的內存的,但是卻很少有人注意到指針本身并沒有發生什么變化。各位可以在VC中使用單步跟蹤一下,你們會驚奇地發現當指針p被調用了free后它的地址值并沒有改變,只是該地址對應的內存中原來有意義的值變成了垃圾,“p”卻還是指向的這塊內存。記住,一定要第一時間將p的值設為NULL,否則會讓別人以為p是一個有意義的指針而誤使用它(當別人使用該指針時會判斷指針的值是否為NULL,如果不為NULL就會以為它有意義)。
<BR> <BR>char *p = (char *)malloc(100);
<BR> <BR>strcpy(p, “hello”);
<BR> <BR>free(p); // the address of “p” is not changed.
<BR> <BR>….
<BR> <BR>if (NULL != p) //it will return TRUE
<BR> <BR> strcpy(p, “world”); //Wrong!!!
<BR> <BR>下面提兩點,讓大家可以防止上面的情況出現: <BR> <BR>1)<FONT
color=#ff0000>指針聲明后要馬上初始化</FONT>。因為指針出現的缺省值是隨機的,所以一定要賦值為NULL,然后再使用。 <BR><BR>2)<FONT
color=#ff0000>調用了free和delete后一定要將指針賦值為NULL</FONT>。原因上面已經提過,就不再贅述。 <BR><BR> <BR> andy_show ( 2001-11-12 16:23:22 )
<BR> <BR>相信有許多文章提到過智能指針的用法,STL的auto_ptr是最好的例子,通過一個Template類實現大部分用new分配的內存的自動釋放。另外一個辦法是通過實現一個Reference Wrapper的Template類來實現基于引用計數的資源的自動釋放,不過開銷要比auto_ptr大,但是好處是可以實現對不同類型的系統資源的自動回收(如Windows系統中的內存,GDI,文件等Handle)。關于如何實現這樣的類可以參考一下VC中_bstr_t的類的實現,雖然這個類只是局限于對于COM的BSTR類型的封裝,不過其中的思想完全可以應用到像Handle那樣的類型中。另為一個比較好的例子是_com_ptr_t的類,應該可以給各位不少啟發。其實只要善用C++的特性,完全可以避免內存泄漏。不過,類似數組越界這樣的問題還是無法避免。<BR><BR><BR>在C++中,我從來都不這樣做。而是:
<BR> <BR>#define SAFE_DELETE(p) (delete (p),(p)=NULL)
<BR> <BR>#if _DEBUG
<BR> <BR>#if defined(new) && defined(MYNEW)
<BR>#undef new
<BR>#endif<BR><BR>void * _cdecl operator new (size_t nSize,LPCSTR pFileName,DWORD dwLine)<BR>{<BR>1、使用其他內存分配函數分配內存<BR>2、做一些操作,記錄內存分配情況和分配次數<BR>3、記錄文件位置<BR>4、小技巧:<BR>_onexit();<BR>怎么用?查查MSDN,或問問其他人<BR>} <BR><BR>inline void * _cdecl operator new (size_t nSize)<BR>{<BR>同上,但是沒有文件位置<BR>}<BR><BR>inline void _cdecl operator delete (void * pMem,LPCSTR pFileName,DWORD dwLine) <BR>{<BR>1、使用其他內存釋放函數<BR>2、根據記錄的內存分配信息來初步確定內存的合法性、越界等并輸出錯誤信息<BR>3、VC中的小技巧(其他的編譯器就不知道了):<BR>char buff[1024];<BR>sprintf(buff,"%s(%d) : 出錯信息\n",pFileName,dwLine,...);<BR>OutputDebugString(buff);<BR>這樣,可以讓VC直接跳到出錯代碼處,當然,僅限于調試運行(F5)并且MFC Trace中設置了輸出調試信息。<BR>}</FONT></DIV>
<DIV><FONT
size=3><BR>inline void _cdecl operator delete (void * pMem)<BR>{<BR>1和2同上。<BR>3。輸出分配這塊內存是第幾次分配的,然后利用 VC 的條件斷點跟蹤出出錯代碼<BR>}<BR><BR>#ifdef MYNEW<BR>#define new MYNEW<BR>#else<BR>#define MYNEW new(__FILE__,__LINE__)<BR>#endif<BR>#endif //end _DEBUG<BR><BR>通過以上步驟,基本可以在調試版本杜絕內存使用錯誤</DIV></FONT><BR>
<DIV class=xspace-imginlog></DIV></DIV>
<P class=xspace-itemlinks><A
onclick="showajaxdiv('http://www.linuxpk.com/blogpost.php?action=import&itemid=7997',400);"
href="javascript:;">導入論壇</A> <A onclick=joinfavorite(7997);
href="javascript:;">收藏</A> <A
onclick="showajaxdiv('http://www.linuxpk.com/batch.common.php?action=emailfriend&itemid=7997', 400);"
href="javascript:;">分享給好友</A> <A
href="http://www.linuxpk.com/batch.manage.php?itemid=7997" target=_blank>管理</A>
<A onclick=report(7997); href="javascript:;">舉報</A> </P>
<P class=xspace-itemtag>TAG: </P>
<DIV id=xspace-itemreply>
<DIV class=xspace-multipage id=xspace-multipage-div><A
onclick=javascript:showcomment(1); href="javascript:;">查看全部評論</A></DIV></DIV>
<DIV id=xspace-itemform>
method=post target=xspace-phpframe>
<FIELDSET id=xspace-rates>
<DIV id=xspace-rates-bg>
<DIV class=xspace-rates0 id=xspace-rates-star></DIV>
<DIV id=xspace-rates-a><A onmouseover=rateHover(-5);
onclick="setRate('-5', '7997');" onmouseout=rateOut();
href="javascript:;">-5</A> <A onmouseover=rateHover(-3);
onclick="setRate('-3', '7997');" onmouseout=rateOut();
href="javascript:;">-3</A> <A onmouseover=rateHover(-1);
onclick="setRate('-1', '7997');" onmouseout=rateOut();
href="javascript:;">-1</A> <A onmouseover=rateHover(0);
onclick="setRate('0', '7997');" onmouseout=rateOut(); href="javascript:;">-</A>
<A onmouseover=rateHover(1); onclick="setRate('1', '7997');"
onmouseout=rateOut(); href="javascript:;">+1</A> <A onmouseover=rateHover(3);
<A onmouseover=rateHover(5); onclick="setRate('5', '7997');"
onmouseout=rateOut(); href="javascript:;">+5</A> </DIV><INPUT
id=xspace-rates-value type=hidden value=0 name=rates> </DIV>
<P>評分:<SPAN id=xspace-rates-tip>0</SPAN></P></FIELDSET>
<FIELDSET><LEGEND>我來說兩句</LEGEND>
<P><SPAN class=xspace-moresmilies onclick=moresmilies();>顯示全部</SPAN> </P>
<DIV id=xspace-smilies><IMG id=smilie_0 onclick=insertSmilies(0)
alt=:loveliness:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/loveliness.gif"
border=0> <IMG id=smilie_1 onclick=insertSmilies(1) alt=:handshake
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/handshake.gif"
border=0> <IMG id=smilie_2 onclick=insertSmilies(2) alt=:victory:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/victory.gif"
border=0> <IMG id=smilie_3 onclick=insertSmilies(3) alt=:funk:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/funk.gif"
border=0> <IMG id=smilie_4 onclick=insertSmilies(4) alt=:time:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/time.gif"
border=0> <IMG id=smilie_5 onclick=insertSmilies(5) alt=:kiss:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/kiss.gif"
border=0> <IMG id=smilie_6 onclick=insertSmilies(6) alt=:call:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/call.gif"
border=0> <IMG id=smilie_7 onclick=insertSmilies(7) alt=:hug:
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/hug.gif"
border=0> <IMG id=smilie_8 onclick=insertSmilies(8) alt=:lol
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/lol.gif"
border=0> <IMG id=smilie_9 onclick=insertSmilies(9) alt=":'("
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/cry.gif"
border=0> <IMG id=smilie_10 onclick=insertSmilies(10) alt=:Q
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/mad.gif"
border=0> <IMG id=smilie_11 onclick=insertSmilies(11) alt=:L
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/sweat.gif"
border=0> <IMG id=smilie_12 onclick=insertSmilies(12) alt=;P
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/titter.gif"
border=0> <IMG id=smilie_13 onclick=insertSmilies(13) alt=:$
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/shy.gif"
border=0> <IMG id=smilie_14 onclick=insertSmilies(14) alt=:P
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/tongue.gif"
border=0> <IMG id=smilie_15 onclick=insertSmilies(15) alt=:o
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/shocked.gif"
border=0> <IMG id=smilie_16 onclick=insertSmilies(16) alt=:@
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/huffy.gif"
border=0> <IMG id=smilie_17 onclick=insertSmilies(17) alt=:D
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/biggrin.gif"
border=0> <IMG id=smilie_18 onclick=insertSmilies(18) alt=:(
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/sad.gif"
border=0> <IMG id=smilie_19 onclick=insertSmilies(19) alt=:)
src="C-C++實戰之內存管理 - rnarldo的個人空間 - Linux寶庫 - Powered by X-Space.files/smile.gif"
border=0> </DIV>
<P></P>
<P><LABEL for=xspace-commentmsg>內容</LABEL> <TEXTAREA id=xspace-commentmsg name=message></TEXTAREA> </P>
<P><LABEL for=xspace-nickname>昵稱</LABEL> <INPUT id=xspace-nickname
name=nickname> </P>
<P><LABEL>加入事件</LABEL> <INPUT type=checkbox CHECKED name=addfeed> </P>
<P id=xspace-seccodeline><LABEL for=xspace-seccode>驗證</LABEL> <INPUT
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -