📄 附录a0 建构环境.htm
字号:
size=2>无疑的,一般程序设计上常见的错误即是在程序代码中忘记关闭或释放一个资源,这也是多数开发者必须面对的情形。为了保证资源在超过使用范围时会被适当地清除,我建立了CensureCleanup之C++
样板类别(Template
Class),如列表B-1所示。因为这个类别是一个样板类别,它可以帮助您清除一般的大部份物件类型。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>我为大部份常见的Microsoft
Windows之资料型别定义了CensureCleanup的特定实例。定义一个型别需要叁种资讯:物件型别、被用来清除物件的函数位址以及一个指示该物件无效的值(通常为NULL或0)。举例来说,为了清除一个核心物件,它的资料型别为HANDLE,用来清除该物件的函数为CloseHandle,以及一个确认该handle为无效的NULL值。同样的,要清除一个动态载入的DLL,它的资料型别为HANDLE,用来清除资源的函数为FreeLibrary,和一个用来确认为无效物件的NULL值。您可以在CEnsureCleanup.h文件后面看到所有用于清除之不同类别。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>使用CensureCleanup类别并不会使事情变得更容易。无论何时,当您平常使用正常的资料类型时,所必须做的事情即是使用一个类别的实例。例如,您不须编写如下的程序代码:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">HANDLE hfile = CreateFile(...); <BR>. <BR>. <BR>. <BR>CloseHandle(hfile);</PRE>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您可以编写如下的样子:</FONT></P><PRE style="LINE-HEIGHT: 25px">CEnsureCloseFile hfile = CreateFile(...); <BR>. <BR>. <BR>.</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>使用C++ 类别资料型态,您不需再呼叫CloseHandle释放资源。当C++
物件超出使用范围时,解构函数(Destructor)会被呼叫,而CloseHandle也会自动被呼叫!事实上,即使是从一个呼叫函数的中途返回或者是产生一个例外,此时物件都保证会被清除。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>顺便一提,您毋须担心管理的部份。我检查了在使用这些类别时,由最佳化编译器所产生的组合语言,其产生的代码正如同您明确地呼叫清除函数的情形。这是因为CensureCleanup函数使用了所有的内嵌函数。我简直爱死了这些类别,而且也不敢相信自己在这么多年的程序设计生涯中竟没有使用到它们。现在我不管什么事几乎都会用到它们。</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">EnsureCleanup.h <BR>/******************************************************************** <BR>模组:EnsureCleanup.h <BR>通告:Copyright (c)2000 Jeffrey Richter <BR>目的:当一个物件超过使用范围时,这些类别会确认物件被清除。请参阅附录B的内容。 <BR>********************************************************************/ <BR>#pragma once // 每次完成编译时,包含此标头档 <BR>/////////////////////////////////////////////////////////////////////////////// <BR>#include "..\CmnHdr.h" // 请参阅附录A <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 资料型别表示物件清除函数的位址 <BR>// 我使用了UINT_PTR以使此类别可在64位元之Windows中适当地执行 <BR>typedef VOID (WINAPI* PFNENSURECLEANUP)(UINT_PTR); <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 每一个范本说明需要一个资料型别、清除函数的位址及一个指示无效的值 <BR>template<class TYPE, PFNENSURECLEANUP pfn, UINT_PTR tInvalid = NULL> <BR>class CEnsureCleanup { <BR>public: <BR> // 预设的建构者假设为一个无效的值(没有东西需被清除) <BR> CEnsureCleanup(){m_t = tInvalid;} <BR> // 此建构者设定该值为一个特定值 <BR> CEnsureCleanup(TYPE t) : m_t((UINT_PTR) t) { } <BR> // 执行清除的解构者 <BR> ~CEnsureCleanup() { Cleanup(); } <BR> // 如果要显示该值是否为一个有效的物件,使用Helper方法告知 <BR> BOOL IsValid() { return(m_t != tInvalid); } <BR> BOOL IsInvalid() { return(!IsValid()); } <BR> // 重新指定物件,强迫现行物件被清除 <BR> TYPE operator=(TYPE t){ <BR> Cleanup(); <BR> m_t = (UINT_PTR) t; <BR> return(*this); <BR> } <BR> // 回传该值(支援32位元及64位元的Windows) <BR> operator TYPE() { <BR> // 如果TYPE是32位元值,转型至32位元的TYPE <BR> // 如果TYPE是64位元值,转型至64位元的TYPE <BR> return((sizeof(TYPE) == 4) ? (TYPE) PtrToUint(m_t) : (TYPE) m_t); <BR> } <BR> // 如果该值显示一个有效的物件,清除该物件 <BR> void Cleanup() { <BR> if (IsValid()) { <BR> // 在64位元Windows中,所有的参数皆为64位元 <BR> // 所以不需转型 <BR> pfn(m_t); // 关闭物件 <BR> m_t = tInvalid; // 我们不再显示一个有效的物件 <BR> } <BR> } <BR>private: <BR> UINT_PTR m_t; // 表示物件的成员 <BR>}; <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 使它变得容易的巨集,为特定资料型别宣告范本类别的实例 <BR>#define MakeCleanupClass(className, tData, pfnCleanup) \ <BR> typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup> className; <BR>#define MakeCleanupClassX(className, tData, pfnCleanup, tInvalid) \ <BR>typedef CEnsureCleanup< tData, (PFNENSURECLEANUP)pfnCleanup, \ <BR>(INT_PTR)tInvalid> className; <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 一般资料型别的C++ 范本类别实例 <BR>MakeCleanupClass(CEnsureCloseHandle, HANDLE, CloseHandle); <BR>MakeCleanupClassX(CEnsureCloseFile, HANDLE, CloseHandle, <BR> INVALID_HANDLE_VALUE); <BR>MakeCleanupClass(CEnsureLocalFree, HLOCAL, LocalFree); <BR>MakeCleanupClass(CEnsureGlobalFree, HGLOBAL, GlobalFree); <BR>MakeCleanupClass(CEnsureRegCloseKey, HKEY, RegCloseKey); <BR>MakeCleanupClass(CEnsureCloseServiceHandle, SC_HANDLE, CloseServiceHandle); <BR>MakeCleanupClass(CEnsureCloseWindowStation, HWINSTA, CloseWindowStation); <BR>MakeCleanupClass(CEnsureCloseDesktop, HDESK, CloseDesktop); <BR>MakeCleanupClass(CEnsureUnmapViewOfFile, PVOID, UnmapViewOfFile); <BR>MakeCleanupClass(CEnsureFreeLibrary, HMODULE, FreeLibrary); <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 释放一个保留区域的特殊类别 <BR>// 因为VirtualFree需要叁个参数,所以要求特殊的类别 <BR>class CEnsureReleaseRegion { <BR>public: <BR> CEnsureReleaseRegion(PVOID pv = NULL) : m_pv(pv) {} <BR> ~CEnsureReleaseRegion() {Cleanup(); } <BR> PVOID operator=(PVOID pv) { <BR> Cleanup(); <BR> m_pv = pv; <BR> return(m_pv); <BR> } <BR> operator PVOID(){return(m_pv);} <BR> void Cleanup() { <BR> if (m_pv != NULL) { <BR> VirtualFree(m_pv, 0, MEM_RELEASE); <BR> m_pv = NULL; <BR> } <BR> } <BR>private: <BR> PVOID m_pv; <BR>}; <BR>/////////////////////////////////////////////////////////////////////////////// <BR>// 为了从heap中释放一个区块的特殊类别 <BR>// 因为HeapFree需要叁个参数,所以要求特殊的类别 <BR>class CEnsureHeapFree { <BR>public: <BR> CEnsureHeapFree(PVOID pv = NULL, HANDLE hHeap = GetProcessHeap()) <BR> :m_pv(pv), m_hHeap(hHeap) {} <BR> ~CEnsureHeapFree() {Cleanup(); } <BR> PVOID operator=(PVOID pv) { <BR> Cleanup(); <BR> m_pv = pv; <BR> return(m_pv); <BR> } <BR> operator PVOID() {return(m_pv); } <BR> void Cleanup() { <BR>if (m_pv != NULL) { <BR> HeapFree(m_hHeap, 0, m_pv); <BR> m_pv = NULL; <BR> } <BR> } <BR>private: <BR> HANDLE m_hHeap; <BR> PVOID m_pv; <BR>}; <BR>///////////////////////////////// End of File /////////////////////////////////</PRE></FONT></DIV>
<CENTER style="LINE-HEIGHT: 25px">
<P></P>
<P class=content_page><STRONG><FONT
color=#ff0033>[1]</FONT></STRONG> <A
href="http://www.acejoy.com/Html/Article/network/6920061106222109_P2.html">[2]</A> <A
href="http://www.acejoy.com/Html/Article/network/6920061106222109_P3.html">[3]</A> <A
href="http://www.acejoy.com/Html/Article/network/6920061106222109_P4.html">[4]</A> <A
href="http://www.acejoy.com/Html/Article/network/6920061106222109_P2.html">下一页</A></P></DIV><BR><BR></CENTER></DIV></DIV></TD></TR></TBODY></TABLE>
<TABLE style="CLEAR: both" cellSpacing=0 cellPadding=0 width="97%">
<TBODY>
<TR>
<TD align=right>
<TABLE>
<TBODY>
<TR>
<TD>阅读:<SPAN id=news_hits></SPAN>
<SCRIPT src="附录A 建构环境.files/GetHits.htm"
type=text/JavaScript></SCRIPT>
次<BR>录入:<A
href="http://www.acejoy.com/User/Info.Asp?UserName=admin">admin</A><BR><BR></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD align=right>【 <A
href="http://www.acejoy.com/Comment.asp?ChannelID=1&Action=Write&InfoID=69">评论</A>
】 【 <A
href="http://www.acejoy.com/User/SendMail.asp?Title=Windows2000 服务器端应用程序开发设计指南-附录"
target=_blank>推荐</A> 】 【 <A href="javascript:window.print()">打印</A>
】 </TD></TR></TBODY></TABLE>
<TABLE style="CLEAR: both" width="97%" align=center>
<TBODY>
<TR>
<TD>上一篇:<A
title="标题:Windows2000 服务器端应用程序开发设计指南-安全连接(3) 作者:Jeffrey Richter Jason D. Clark 更新:2006-11-3 18:43:26 点击:365"
href="http://www.acejoy.com/Html/Article/network/6820061103184326.html">Windows2000
服务器端应用程序开发设计指南-安全连接(3)</A><BR>下一篇:<A
title="标题:Windows Sockets 规范及应用-Windows网络编程接口 作者:施炜,李铮,秦颖 更新:2006-11-18 22:57:20 点击:0"
href="http://www.acejoy.com/Html/Article/network/7620061118225720.html">Windows
Sockets 规范及应用-Windows网络编程接口</A> </TD></TR></TBODY></TABLE></TD>
<TD class=mr></TD></TR></TBODY></TABLE></DIV></DIV>
<DIV class=mframe>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center>
<TBODY>
<TR>
<TD class=tl></TD>
<TD class=tm><SPAN class=tt>相关新闻</SPAN> </TD>
<TD class=tr></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center>
<TBODY>
<TR>
<TD class=ml></TD>
<TD class=mm>
<TABLE height="100%" cellSpacing=5 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD vAlign=top>
<SCRIPT language=javascript
src="附录A 建构环境.files/GetCorrelative.htm"></SCRIPT>
</TD></TR></TBODY></TABLE></TD>
<TD class=mr></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center>
<TBODY>
<TR>
<TD class=tl></TD>
<TD class=tm><SPAN class=tt>本文评论</SPAN> </TD>
<TD class=tr></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center>
<TBODY>
<TR>
<TD class=ml></TD>
<TD class=mm>
<P> </P>
<TABLE height="100%" cellSpacing=5 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD vAlign=top>
<SCRIPT language=javascript
src="附录A 建构环境.files/Comment.htm"></SCRIPT>
</TD></TR></TBODY></TABLE></TD>
<TD class=mr></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center>
<TBODY>
<TR>
<TD class=ml></TD>
<TD class=mm></TD>
<TD class=mr></TD></TR></TBODY></TABLE></DIV>
<TABLE id=footer cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR style="LINE-HEIGHT: 130%" align=middle>
<TD height=23> <A
href='javascript:window.external.addFavorite("http://www.acejoy.com","ACE开发者")'><FONT
color=#000000>加入收藏</FONT></A> - <A
href="http://www.acejoy.com/Help.asp?Action=aboutweb" target=_blank><FONT
color=#000000>关于本站</FONT></A> - <A class=Bottom
href="http://www.acejoy.com/Help.asp?Action=Copyright" target=_blank><FONT
color=#000000>版权申明</FONT></A> - <A class=Bottom
href="http://www.acejoy.com/Help.asp?Action=aboutweb" target=_blank><FONT
color=#000000>联系站长</FONT></A> - <A class=Bottom
href="http://www.acejoy.com/LinkSite.asp" target=_blank><FONT
color=#000000>友情链接</FONT></A> </TD></TR>
<TR align=middle>
<TD height=23>Copyright© 2004-2006 <A
href="http://www.acejoy.com/">http://www.acejoy.com/</A> .All Rights
Reserved <A href="http://www.miibeian.gov.cn/" target=_blank>京ICP备06055248
</A>
<SCRIPT language=JavaScript src="附录A 建构环境.files/stat.htm"
charset=gb2312></SCRIPT>
</TD></TR></TBODY></TABLE>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV><!--Powered by:CreateLive CMS Version 3.1(www.acejoy.com) CreateDate:2007-3-4 10:50:34--></DIV></DIV></DIV></DIV></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -