📄 csdn_文档中心_正确使用内存.htm
字号:
style="FONT-FAMILY: 宋体">栈中分配的空间的生命期与这个变量所在的函数和类相关。如果是函数中定义的局部变量,那么它的生命期就是函数被调用时,如果函数运行结束,那么这块内存就会被回收。如果是类中的成员变量,则它的生命期与类实例的生命期相同<SPAN
lang=EN-US><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>3.在堆上分配的内存,生命期是从调用new或者malloc开始,到调用delete或者free结束。如果不掉用delete或者free。则这块空间必须到软件运行结束后才能被系统回收。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>下面我们再看看,在使用内存的过程中,我们经常发生一些什么样的错误。以及我们应该采取哪些对策。<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN: 0cm 0cm 0pt"><FONT face=宋体
size=3>发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>常见的内存错误及其对策如下:<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>1<SPAN
style="mso-spacerun: yes">
</SPAN>内存分配未成功,却使用了它。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为<SPAN
lang=EN-US>NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL)
或if(p!=NULL)进行防错处理。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>2<SPAN
style="mso-spacerun: yes">
</SPAN>内存分配虽然成功,但是尚未初始化就引用它。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>3<SPAN
style="mso-spacerun: yes">
</SPAN>内存分配成功并且已经初始化,但操作越过了内存的边界。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>例如在使用数组时经常发生下标“多<SPAN
lang=EN-US>1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>4<SPAN
style="mso-spacerun: yes">
</SPAN>忘记了释放内存,造成内存泄露。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>动态内存的申请与释放必须配对,程序中<SPAN
lang=EN-US>malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>5<SPAN
style="mso-spacerun: yes">
</SPAN>释放了内存却继续使用它。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>有三种情况:<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>(<SPAN
lang=EN-US>1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>(<SPAN
lang=EN-US>2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>(<SPAN
lang=EN-US>3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>综上所述,我们应该注意:<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>1.用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>2.不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>3.避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>4.动态内存的申请与释放必须配对,防止内存泄漏。<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN
lang=EN-US
style="FONT-FAMILY: 宋体">5.用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”</SPAN><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt">。<SPAN
lang=EN-US><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>下面举几个经典的错误例子,大家不要犯同样的错误:<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo4; tab-stops: list 18.0pt"><SPAN
lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=3>1.</FONT><SPAN
style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>返回栈内存指针<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>char
*GetString(void)<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>{<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>char *p = "hello
world";<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>return
p;<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>}<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>char* pGet =
GetString();<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT
size=3>这段程序编译时没有错误,运行也没有错误,但是你却无法使得返回的<SPAN
lang=EN-US>pGet指针指向的数据是你想要的“hello
world”,因为指针p的生命期是函数GetString内,运行完函数GetString后,p分配的栈空间马上被系统回收了。虽然pGet指向了p当初分配的内存地址,但是那块地址已经没有内容了。<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT
size=3>2.这是一个出现频率非常高的错误<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>char* pChar = new
char;<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>……<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>int a
;<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>pChar =
&a;<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>……<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体"><FONT size=3>delete
pChar;<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>当然这是一个例子,具体的程序各有不同。<SPAN
lang=EN-US><o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体"><FONT size=3>这段程序有两个问题。一是<SPAN
lang=EN-US>pChar =
&a;将导致pChar原先分配的空间无法再被获取,就象我们的丢失了朋友的电话号码一样,无法再联系这个朋友了。这就造成了内存泄漏。如果内存泄漏多了,可能导致系统的崩溃,因为可用的资源将越来越少,直到枯竭为止。第二个问题是delete
pChar将导致异常发生,因为这时的pChar已经不是指向动态分配的内存了,而是指向了a分配的栈空间,而栈空间是不能使用delete来回收的,因此将导致内存异常。</SPAN></FONT></SPAN></P><SPAN
lang=EN-US
style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN
style="mso-tab-count: 1">
</SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">内存是财富,正确使用财富是关键,为人如此,编程也如此。</SPAN><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE align=center bgColor=#006699 border=0 cellPadding=0 cellSpacing=0
width=770>
<TBODY>
<TR bgColor=#006699>
<TD align=middle bgColor=#006699 id=white><FONT
color=#ffffff>对该文的评论</FONT></TD>
<TD align=middle>
<SCRIPT src="CSDN_文档中心_正确使用内存.files/readnum.htm"></SCRIPT>
</TD></TR></TBODY></TABLE>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TD bgColor=#cccccc colSpan=3><SPAN style="COLOR: #cccccc"><IMG height=16
hspace=1 src="CSDN_文档中心_正确使用内存.files/ico_pencil.gif" width=16>
</SPAN> northeaster <I>(2004-5-3 8:56:02)</I>
</TD></TR>
<TR>
<TD bgColor=#ffffff colSpan=3
width=532><BR>内存是财富,正确使用财富是关键,为人如此,编程也如此。说的极是。 <BR></TD></TR></TBODY></TABLE>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TD bgColor=#cccccc colSpan=3><SPAN style="COLOR: #cccccc"><IMG height=16
hspace=1 src="CSDN_文档中心_正确使用内存.files/ico_pencil.gif" width=16>
</SPAN> zhaoyifei1 <I>(2004-4-29 16:26:21)</I>
</TD></TR>
<TR>
<TD bgColor=#ffffff colSpan=3 width=532><BR>好文!!
<BR></TD></TR></TBODY></TABLE><BR>
<DIV align=center>
<TABLE align=center bgColor=#cccccc border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#006699 id=white><FONT
color=#ffffff>我要评论</FONT></TH></TR></TBODY></TABLE></DIV>
<DIV align=center>
<TABLE border=0 width=770>
<TBODY>
<TR>
<TD>你没有登陆,无法发表评论。 请先<A
href="http://www.csdn.net/member/login.asp?from=/Develop/read_article.asp?id=27268">登陆</A>
<A
href="http://www.csdn.net/expert/zc.asp">我要注册</A><BR></TD></TR></TBODY></TABLE></DIV><BR>
<HR noShade SIZE=1 width=770>
<TABLE border=0 cellPadding=0 cellSpacing=0 width=500>
<TBODY>
<TR align=middle>
<TD height=10 vAlign=bottom><A
href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</A> - <A
href="http://www.csdn.net/map/map.shtm">网站地图</A> - <A
href="http://www.csdn.net/help/help.asp">帮助信息</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=2">联系方式</A> - <A
href="http://www.csdn.net/english">English</A> </TD>
<TD align=middle rowSpan=3><A
href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG
border=0 height=48 src="CSDN_文档中心_正确使用内存.files/biaoshi.gif"
width=40></A></TD></TR>
<TR align=middle>
<TD vAlign=top>百联美达美公司 版权所有 京ICP证020026号</TD></TR>
<TR align=middle>
<TD vAlign=top><FONT face=Verdana>Copyright © CSDN.net, Inc. All rights
reserved</FONT></TD></TR>
<TR>
<TD height=15></TD>
<TD></TD></TR></TBODY></TABLE></DIV>
<DIV></DIV><!--内容结束//--><!--结束//--></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -