📄 9_2_4 使用垃圾回收算法来做内存泄漏检查 - 《多任务下的数据结构与算法》 - 免费试读 - book_csdn_net.htm
字号:
urchinTracker();
</SCRIPT>
<!-- /公共页头 --><LINK
href="C:\Documents and Settings\K&G\桌面\9_2_4 使用垃圾回收算法来做内存泄漏检查 - 《多任务下的数据结构与算法》 - 免费试读 - book_csdn_net.files\style(1).css"
type=text/css rel=stylesheet>
<DIV id=booknav2>
<DIV id=booknavtop>
<UL>
<LI><A href="http://book.csdn.net/">首页</A> </LI>
<LI><A href="http://book.csdn.net/book/morelz.aspx">精品连载</A> </LI>
<LI><A href="http://club.book.csdn.net/people/myclub.aspx">我的书友会</A> </LI>
<LI><A href="http://club.book.csdn.net/people/putblog.aspx">图书秀</A> </LI>
<LI><A href="http://club.book.csdn.net/people/alllist.aspx">书架</A> </LI>
<LI><A href="http://blog.csdn.net/group/bookread/" target=_blank>圈子</A> </LI>
<LI><A href="http://down.csdn.net/app/list.php?tid=502" target=_blank>资源下载</A>
</LI>
<LI><A href="http://bank.csdn.net/" target=_blank><FONT
style="FONT-WEIGHT: bold">银行</FONT></A> </LI></UL></DIV>
<SCRIPT type=text/javascript>
function IsBlank(obj) //查看对象的值是否为空
{
if(obj.replace(/^\s+|\s+$/,"")=="")
{
return true;
}
else
{
return false;
}
}
function SearchBook_Top()
{
if( !IsBlank(document.getElementById("txtTopKey").value))
{
var loc;
var szType;
if(document.getElementById("listSearchType").value==null)
{
szType= document.getElementById("listSearchType").options(document.getElementById("listSearchType").selectedIndex).value;
}
else
{
szType= document.getElementById("listSearchType").value;
}
if(szType==1)
loc="http://book.csdn.net/book/morelz.aspx?key="+escape(document.getElementById("txtTopKey").value);
else
loc="http://club.book.csdn.net/book/s.aspx?key="+escape(document.getElementById("txtTopKey").value);
self.location=loc;
}
}
</SCRIPT>
<DIV id=booknavbottom2>
<DIV class=hotleft><A href="http://book.csdn.net/subject/allbook.htm"
target=_blank>全部图书</A> <FONT color=red>推荐</FONT>:<A
href="http://club.book.csdn.net/book/s.aspx?key=asp.net">ASP.NET</A> <A
href="http://club.book.csdn.net/book/s.aspx?key=ajax">Ajax</A> <A
href="http://club.book.csdn.net/book/s.aspx?key=spring">Spring</A> <A
href="http://club.book.csdn.net/book/s.aspx?key=Hibernate">Hibernate</A> <A
href="http://club.book.csdn.net/book/s.aspx?key=Java">Java</A></DIV>
<DIV class=hotright><SELECT id=listSearchType name=aa> <OPTION value=2
selected>书友会</OPTION> <OPTION value=1>连载</OPTION></SELECT><INPUT
onkeypress=if(event.keyCode==13){SearchBook_Top();} id=txtTopKey maxLength=25><INPUT onclick=SearchBook_Top(); type=button value=搜索 name=提交></DIV></DIV></DIV>
<DIV class=area>
<SCRIPT
src="9_2_4 使用垃圾回收算法来做内存泄漏检查 - 《多任务下的数据结构与算法》 - 免费试读 - book_csdn_net.files/BookDetailAd.js"
type=text/javascript></SCRIPT>
<DIV class=col1>
<DIV class=lineBlue></DIV><!-- title -->
<DIV class=arcTitle>
<H1><A href="http://book.csdn.net/bookfiles/65">多任务下的数据结构与算法 </A></H1>
<DIV style="FONT-SIZE: 15px; TEXT-ALIGN: center"><A
href="http://book.csdn.net/bookfiles/65/100652571.shtml">9.2.4 使用垃圾回收算法来做内存泄漏检查
</A></DIV>
<DIV style="FONT-SIZE: 15px; TEXT-ALIGN: center"><A class=url
href="http://book.csdn.net/">http://book.csdn.net/</A> 2006-8-14 14:19:00 </DIV>
<DIV class=clear></DIV>
<DIV
style="BORDER-RIGHT: #0b5f98 1px solid; BORDER-TOP: #0b5f98 1px solid; MARGIN: 0px auto; BORDER-LEFT: #0b5f98 1px solid; WIDTH: 700px; BORDER-BOTTOM: #0b5f98 1px solid">
<DIV
style="PADDING-RIGHT: 1px; PADDING-LEFT: 1px; FLOAT: left; PADDING-BOTTOM: 1px; WIDTH: 16px; COLOR: white; PADDING-TOP: 1px; BACKGROUND-COLOR: #0b5f98">图书导读
</DIV>
<DIV
style="PADDING-LEFT: 2px; FLOAT: right; WIDTH: 670px; LINE-HEIGHT: 16pt; TEXT-ALIGN: left"><!--导读-->
<H1 id=divCurrentNode
style="PADDING-LEFT: 2px; FONT-SIZE: 12px; WIDTH: 100%; COLOR: #b83507; TEXT-ALIGN: left">当前章节:<A
href="http://book.csdn.net/bookfiles/65/100652571.shtml"><FONT color=red>9.2.4
使用垃圾回收算法来做内存泄漏检查</FONT></A></H1>
<DIV id=divRelateNode style="PADDING-LEFT: 2px">
<DIV style="FLOAT: left; WIDTH: 49%">·<A
href="http://book.csdn.net/bookfiles/65/100652568.shtml">9.2.1
垃圾收集算法简介</A></DIV>
<DIV style="FLOAT: right; WIDTH: 49%">·<A
href="http://book.csdn.net/bookfiles/65/100652569.shtml">9.2.2
用户层垃圾回收算法的实现</A></DIV>
<DIV style="FLOAT: left; WIDTH: 49%">·<A
href="http://book.csdn.net/bookfiles/65/100652570.shtml">9.2.3
多任务下的垃圾收集</A></DIV></DIV></DIV></DIV>
<DIV class=clear></DIV></DIV><!-- main -->
<DIV id=main>
<DIV id=text>
<DIV id=csdn_zhaig_ad_yahoo_2></DIV>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><SPAN
lang=EN-US>9.2.4</SPAN><SPAN lang=EN-US> </SPAN><SPAN
style="FONT-FAMILY: 方正准圆简体">使用垃圾回收算法来做内存泄漏检查</SPAN></H3>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 华康简宋">使用引用计数的方法实现的内存垃圾回收不能自动回收循环引用的内存,循环引用的内存需要使用手工进行释放,但手工释放很可能由于编程人员的失误导致内存泄漏,所以必须检查是否存在内存泄漏。要完成这项任务,只要在程序退出时检查一下哈希表中还有哪些内存的引用计数不为</SPAN><SPAN
lang=EN-US>0</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">,就可以知道有哪些内存还没有被释放,内存没有被释放的原因有以下两种。</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 华康简宋">①</SPAN> <SPAN
style="FONT-FAMILY: 华康简宋">内存是供全局使用的,必须等到要退出时才能释放</SPAN><SPAN
style="FONT-FAMILY: 宋体">;</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 华康简宋">②</SPAN> <SPAN
style="FONT-FAMILY: 华康简宋">内存中有循环引用,导致不能释放。</SPAN></P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 华康简宋">还需要知道哈希表中保存的内存地址指向的内存是在程序的哪一行分配的,才能定位到具体发生泄漏的位置。</SPAN><SPAN
lang=EN-US>C</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">语言中有一个宏可以获取源程序中的行号,下面就用这个宏来实现内存泄漏检查。</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 华康简宋">内存泄漏只是在软件的</SPAN><SPAN
lang=EN-US>DEBUG</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">版本才需要用到,因此下面就来设计一个</SPAN><SPAN
lang=EN-US>DEBUG</SPAN><SPAN style="FONT-FAMILY: 华康简宋">版本的内存垃圾回收。</SPAN></P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 华康简宋; LETTER-SPACING: 0.3pt">首先要修改内存中需要保存的数据,除了保存引用计数外,还需要保存分配这块内存的源程序文件名和行号,还要保存分配内存的大小信息。为方便起见,可以将引用计数和内存大小保存在分配内存的头部,行号和文件名保存在分配内存的尾部,如图</SPAN><SPAN
lang=EN-US style="LETTER-SPACING: 0.3pt">9-6</SPAN><SPAN
style="FONT-FAMILY: 华康简宋; LETTER-SPACING: 0.3pt">所示。</SPAN></P>
<P class=0><SPAN lang=EN-US><IMG height=26 alt="" src="" width=384></SPAN></P>
<P class=1><SPAN style="FONT-FAMILY: 黑体">图</SPAN><SPAN lang=EN-US>9-6
</SPAN><SPAN style="FONT-FAMILY: 黑体">检查内存泄漏需要保存的数据</SPAN></P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 华康简宋">关于获取源程序文件名和行号,可以使用宏</SPAN><SPAN
lang=EN-US>_FILE_</SPAN><SPAN style="FONT-FAMILY: 华康简宋">和</SPAN><SPAN
lang=EN-US>_LINE_</SPAN><SPAN style="FONT-FAMILY: 华康简宋">来获取,要注意的是,</SPAN><SPAN
lang=EN-US>_LINE_</SPAN><SPAN style="FONT-FAMILY: 华康简宋">和</SPAN><SPAN
lang=EN-US>_FILE_</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">是调用它们的地方的源文件名和行号,如果简单地在</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">函数中使用这两个宏,那么所有调用</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">函数的地方获得的源文件名和行号都是</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">函数的源文件名和行号,所有获取的源文件名和行号均相同,显然达不到预想的目的。</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 华康简宋">预想的目的是为了获取调用</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">处的源文件名和行号,因此需要将</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">函数定义成宏,这样在调用它的地方就会将编码展开,便能得到正确的调用</SPAN><SPAN
lang=EN-US>GC_Malloc()</SPAN><SPAN
style="FONT-FAMILY: 华康简宋">处的源文件名和行号,有助于确认发生内存泄漏的位置及原因。</SPAN></P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 华康简宋">通常只要在程序的调试版本中检查内存泄漏就可以了,修改后对应的</SPAN><SPAN
lang=EN-US>GC_Malloc( )</SPAN><SPAN style="FONT-FAMILY: 华康简宋">和</SPAN><SPAN
lang=EN-US>GC_Free( )</SPAN><SPAN style="FONT-FAMILY: 华康简宋">函数如下。</SPAN></P>
<P class=MsoNormal style="MARGIN-TOP: 8pt; LINE-HEIGHT: 14pt"><STRONG><SPAN
lang=EN-US style="FONT-SIZE: 9pt">#ifdef _DEBUG</SPAN></STRONG></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><STRONG><SPAN lang=EN-US
style="FONT-SIZE: 9pt">#define GC_Malloc(size)\</SPAN></STRONG></P>
<P class=MsoNormal style="MARGIN-TOP: 8pt; LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt">{\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> void
*p</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">;</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 9pt">\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> INT
*q</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">;</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 9pt">\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> char
*psz</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">;</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 9pt">\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> \</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> p = malloc(
size + DOUBLE_INT_LEN + INT_LEN + strlen(__FILE__) + 1)</SPAN><SPAN
style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">;</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 9pt">\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14.3pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> if ( p == NULL
)\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14.3pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt"> {\</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 14.3pt"><SPAN lang=EN-US
style="FONT-SIZE: 9pt">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -