CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  扩充话题 >  灌水乐园

[原创]实现C语言自动释放资源的方法与探讨

楼主china_win2000()2006-11-04 13:16:05 在 扩充话题 / 灌水乐园 提问

[原创]实现C语言自动释放资源的方法与探讨  
  在函数退出时,实现某些子函数(例如:释放内存,关闭句柄)调用的自动化有两个好处:  
  1、 减少程序员劳动强度,使得代码变得更加简洁顺畅。增强代码的可读性。  
  2、 增强代码的健壮性。  
   
  在C语言中如何释放资源?我们必需把return   语句替换成如下这样:  
   
  #define   vreturn     returnfunc();       return  
   
  #define   LIST_NAME       g_unique_exit_head_list  
  #define   LOCAL_EXIT_INIT     PCALL_LIST   LIST_NAME=NULL  
  #define   LSET_EXIT_FUNC   setexitfunc  
   
  typedef   struct   _M_MM{  
  struct   _M_MM   *pNext;                       //指向下一个要释放的资源节点  
  DWORD     ParamSpace;                     //资源释放函数需要的参数字节数  
  LPVOID   pFunc;                                 //释放资源的函数  
  DWORD   param[1];                           //可变长数组,存放参数  
  }CALL_LIST,*PCALL_LIST;  
   
  为了说明问题,下面请看一段代码  
  ….  
  If((FileHandle=CreateFile(…)==0)  
  {  
          ….  
          return   STATUS_ERROR;  
  }  
  ….  
  If((pmem=VirtuallAlloc(…)==0)  
  {  
          …  
          CloseHandle(FileHandle);  
          return   STATUS_ERROR;  
  }  
  ….  
  以上代码替换成如下这个样子  
   
  ….  
   
  If((FileHandle=CreateFile(…)==0)  
  {  
          ….  
          vreturn   STATUS_ERROR;  
  }  
  LSET_EXIT_FUNC(LIST_HEAD,1,CloseHandle,   FileHandle);  
   
  ….  
  If((pmem=VirtuallAlloc(…)==0)  
  {  
      //CloseHandle(FileHandle);     本应在退出之前加入这句,把return换成vreturn之后就不用了。  
          vreturn   STATUS_ERROR;  
  }  
  LSET_EXIT_FUNC(LIST_HEAD,1,VirtualFree,   pmem);  
   
  ….  
   
  这种释放资源的方法,将在下一个产品作为一个标准的编码方法引入,以便减少退出之前忘了调用相关函数而产生的错误。这种错误一旦发生,往往出错位置比较隐蔽,在实验室当中肯定无法重现,而且需要客户配合才能解决。  
   
  说了这么多,不知道细心的朋友是否会注意到,因为退出的时候,需要调用不同的函数释放资源。那么肯定会面临这样一个问题:被用来释放资源的函数,可能是_stdcall函数,可能是_cdecl类型,可能有的函数需要三个参数,有的却不需要参数。  
  对于_stdcall类型的函数,我的实现方法如下:  
   
  returnfunc()  
  {  
   
  PCALL_LIST   pList,pListNext;  
  for(pList   =   m_pList;pList;) //   m_pList   链表头。  
  {  
  callapi(pList); //调用释放资源函数  
  pListNext=pList->pNext;  
  delete   pList; //释放链表本身  
  pList=pListNext;  
  }  
  }  
  void   callapi(PCALL_LIST   pList)                       //调用释放资源函数  
  {  
  BYTE   *pesp,*pnewesp;  
  DWORD   ParamSpace;  
   
  ParamSpace   =   pList->ParamSpace;         //释放API函数用到的参数字节数。参数个数*SIZEOF(DWORD)  
  _asm   mov   pesp,esp;                   //  
  pesp   -=   ParamSpace;                   //把参数拷贝到当前ESP所指的位置  
  pnewesp   =   pesp;                                                   //为了下一步调用的函数,设置参数  
  memcpy(pesp,pList->param,ParamSpace);         //  
  pesp   =   (BYTE*)pList->pFunc;                           //  
  _asm{  
  mov   eax,pesp  
  mov   esp,pnewesp  
  call   eax                                               //这里调用释放资源函数,因为是_STDCALL函数,  
  //所以不需要自己填平堆栈,如果是_cdecl函数,  
  //应该如何填平堆栈呢?因为esp已经变化了,  
  //应该如何知道esp的正确位置呢??  
  }  
  }  
   
   
  对于_cdecl类型的函数如何调用,我还没有很好的方法,如何恢复堆栈。各位高人一起想想看:)。  
   
  本人文字功底极差,拙作有狗屁不通的地方,各位同志海涵。英国大主教彼得说过:重在参和。呵呵  
   
   
  欢迎访问我的博客  
   
  我的其他文章(writing...):  
  vmware   二进制重编译技术分析  
  虚拟机技术在安全领域的应用探讨。  
  intel新一代CPU虚拟机监控技术VMM(virtual   machine   moniter)在安全领域方面的应用展望  
  虚拟机技术在调试器当中应用的可行性分析(是否以后破解会非常easy?)  
  HASH表+二叉树搜索树是否可以让搜索做到多快好省??  
   
   
  顺便说一句,我们公司招人,希望能和各位牛人成为同事。  
  symantec诚聘windows.linux.java软件工程师,高级软件工程师,高级测试工程师(合格者可内部推荐)  
  http://community.csdn.net/Expert/topic/5129/5129494.xml?temp=.7977869  
  问题点数:0、回复次数:0Top

相关问题

关键词

得分解答快速导航

  • 帖主:china_win2000

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo