CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

new中抛出的异常问题。

楼主james_razor(蹬三轮的)2001-08-29 16:26:42 在 C/C++ / C语言 提问

抛出异常?  
  w   k,这么酷的名词,我岂能落后于时代的潮流。  
  管它3721,我抛,我抛,我再抛!  
  好了,这下问题来了:  
  在new中抛出异常的话,赋值过程无法完成(return在throw前,就先返回了,throw在return前,return就执行不到)。在最近一层的try-catch测试块中,编译器会调用delete来释放内存。但问题是,没有赋值怎么能释放?于是乎,又一个异常抛出,够酷吧,这下彻底没救了。  
  是不是new中就不能抛出异常啊? 问题点数:200、回复次数:20Top

1 楼ripper(rIPPER)回复于 2001-08-29 16:30:11 得分 0

new里面还要甩异常啊~~   倒~~     Top

2 楼fsb_12345(myself)回复于 2001-08-29 16:33:22 得分 0

gzTop

3 楼james_razor(蹬三轮的)回复于 2001-08-29 16:46:31 得分 0

比如说,内存不够的时候,我抛之。  
  但tmd的delete你瞎忙乎什么呢,该删的时候不删,不用你删你到挺起劲的。  
  new你也正是的,你抛就抛呗,没人不让你抛,但好歹你也给那个变量赋个NULL,delete就不会不识好歹的大叫“有异常!”了。  
  new委屈的:这也不是我的错,系统这样规定的。  
  wk,那你找个人把系统干掉,再找个人把你也干掉,有这样的废物系统,还有你这样的废物指令,你们两个合起来整我啊。Top

4 楼xiterator(xi)回复于 2001-08-29 16:51:34 得分 0

全局void*   operator   new中throw   std::bad_alloc()异常时,是由于所请求的内存没有申请到,所以对于heap没有什么要做的工作(包括delete的调用也不需要),可以说全局void*   operator   new中抛出异常客户代码/库代码没有什么除了撤消调用stack   frame中的对象或信息外没有什么特别需要做的。Top

5 楼james_razor(蹬三轮的)回复于 2001-08-29 16:56:56 得分 0

喂,老兄,你这话我怎么看上去这么别扭啊,老实交待,是不是字典翻译的?  
  其实在new之前,先对变量赋NULL,可以解决这个问题,但是不够地道,而且容易忘。Top

6 楼xiterator(xi)回复于 2001-08-29 17:20:10 得分 0

有些编译器在new失败时并不抛出异常(vc++),而是返回0。  
  若抛出bad_alloc()异常,客户要么没有catch,要么设置了catch块,可以在catch块中对这种情况加以处理(p=0之类的)。  
  关于exception   handling   中new   抛出异常处理可参见   <<Inside   The   C++   Object   Model>>   p301.Top

7 楼onetwothree(onetwothree)回复于 2001-08-29 17:20:33 得分 60

调用new确实可能(因为存储耗尽)抛出异常。但是,对于用new分配的存储,编译器不会自动调用delete去释放(必须你自己调用去释放)。所以,你的假设是不成立的。Top

8 楼james_razor(蹬三轮的)回复于 2001-08-29 17:32:44 得分 0

我这不是假设,而是昨天调出来的问题。Top

9 楼shgciom(一条小鱼)回复于 2001-08-29 17:56:22 得分 0

把源代码公布!看看不就解决许多纠纷了!?Top

10 楼james_razor(蹬三轮的)回复于 2001-08-29 18:08:41 得分 0

明儿吧,谢谢各位。Top

11 楼james_razor(蹬三轮的)回复于 2001-08-30 11:47:57 得分 0

各位对不起,我错了。  
  new中抛出的异常不会引起delete操作。问题中的delete其实是由一个正常的析构函数调用的。调试过程中没看清楚,在new中一抛出异常,在delete就出现错误提示。给人的直觉这两件事情是直接因果相关的。也没细细推敲。浪费大家时间,对不起again。  
  而另一个例子:  
  #include   <iostream>  
   
  using   namespace   std;  
   
  class   Test  
  {  
  static   int   i;  
  public:  
  Test()  
  {  
  cout   <<   "Constructing   Test   obj."   <<   endl;  
  if   (i   ++   ==   3)  
  throw   3;  
  }  
  ~Test()  
  {  
  cout   <<   "Destructing   Test   obj."   <<   endl;  
  }  
  void   *operator   new   []   (size_t   size)   throw   (int)  
  {  
  cout   <<   "Allocating   memory."   <<   endl;  
  return   ::new   char[size];  
  }  
  void   operator   delete   []   (void   *p)  
  {  
  cout   <<   "Release   memory."   <<   endl;  
  ::delete   []p;  
  }  
  };  
   
  int   Test::i   =   0;  
   
  void   main()  
  {  
  try  
  {  
  Test   *t   =   new   Test[10];  
  }  
  catch   (int)  
  {  
  cout   <<   "I   catch   it!"   <<   endl;  
  }  
  }  
  抛出异常是在::new分配内存之后,构造函数中。异常导致构造函数失败,而对上一层的new[]来说,内存已经分配后产生了异常,已分配的内存不能白白让其废弃,否则岂不是有悖异常处理的原则,于是异常处理系统调用delete做清除工作。这里的delete接收参数并不是从new[]赋值的那个变量得到的,而是由系统记录的,所以不存在我所说的问题。  
  好了,分析结束,不正指出,恳请各位不吝赐教。  
   
  new:嘿嘿,不是我的错吧,愈加之罪何患无词,象你这样的人我见得多了,什么大风浪我没经历过,最后的结果还不是一样,我看你还是好好你蹬三轮这份很有前途的职业去吧,不要在这里丢人现眼了。  
  蹬三轮的蹬着车儿远去……   一缕萧瑟影,两行辛酸泪。Top

12 楼Great_Bug()回复于 2001-08-30 12:55:55 得分 0

我是来听课的,,,,,搭你的车行不行?????Top

13 楼ed9er(始祖鸟)回复于 2001-08-30 13:12:03 得分 20

ctor中抛异常,可以专门写出一本书  
   
  所以我从来不,以后也决不会在我写的ctor里抛异常Top

14 楼james_razor(蹬三轮的)回复于 2001-08-31 09:27:13 得分 0

Because   a   constructor   has   no   return   value,   you’ve   previously   had   two   choices   to   report   an   error   during   construction:  
  1.   Set   a   nonlocal   flag   and   hope   the   user   checks   it.  
  2.   Return   an   incompletely   created   object   and   hope   the   user   checks   it.  
  This   is   a   serious   problem   because   C   programmers   have   come   to   rely   on   an   implied   guarantee   that   object   creation   is   always   successful,   which   is   not   unreasonable   in   C   where   types   are   so   primitive.   But   continuing   execution   after   construction   fails   in   a   C++   program   is   a   guaranteed   disaster,   so   constructors   are   one   of   the   most   important   places   to   throw   exceptions   –   now   you   have   a   safe,   effective   way   to   handle   constructor   errors.   However,   you   must   also   pay   attention   to   pointers   inside   objects   and   the   way   cleanup   occurs   when   an   exception   is   thrown   inside   a   constructor.  
  (摘自Thinking   in   C++)Top

15 楼cgaga(红枫剪影)回复于 2001-08-31 11:37:14 得分 0

永远别在构造函数和析构函数中干那些请求系统资源的傻事  
  一切OK!Top

16 楼binglex()回复于 2001-08-31 11:48:56 得分 20

一般在构造函数中只是简单的赋值,不要请求内存分配什么的,因为构造函数没有返回值,你不知道是否成功;  
   
  好的做法是构造函数中把指针设NULL,然后专门加个Init()函数,进行内存分配等可能出错的初始化工作Top

17 楼xiterator(xi)回复于 2001-08-31 14:23:22 得分 100

VC++在设计类时,经常采用的就是二次对象构造法,用起来感觉别扭,明明一步的工作要二步来做,而出错时的处理基本上与在构造函数中throw异常处理相同,而且程序又有多少次会在构造函数中出错呢?看看C++   creator   Bjarne   Stroustrup关于这方面的意见:  
   
  Why   doesn't   C++   provide   a   "finally"   construct?  
  Because   C++   supports   an   alternative   that   is   almost   always   better:   The   "resource   acquisition   is   initialization"   technique   (TC++PL3   section   14.4).   The   basic   idea   is   to   represent   a   resource   by   a   local   object,   so   that   the   local   object's   destructor   will   release   the   resource.   That   way,   the   programmer   cannot   forget   to   release   the   resource.   For   example:    
  class   File_handle   {  
  FILE*   p;  
  public:  
  File_handle(const   char*   n,   const   char*   a)  
  {   p   =   fopen(n,a);   if   (p==0)   throw   Open_error(errno);   }  
  File_handle(FILE*   pp)  
  {   p   =   pp;   if   (p==0)   throw   Open_error(errno);   }  
   
  ~File_handle()   {   fclose(p);   }  
   
  operator   FILE*()   {   return   p;   }  
   
  //   ...  
  };  
   
  void   f(const   char*   fn)  
  {  
  File_handle   f(fn,"rw"); //   open   fn   for   reading   and   writing  
  //   use   file   through   f  
  }  
   
  In   a   system,   we   need   a   "resource   handle"   class   for   each   resource.   However,   we   don't   have   to   have   an   "finally"   clause   for   each   acquisition   of   a   resource.   In   realistic   systems,   there   are   far   more   resource   acquisitions   than   kinds   of   resources,   so   the   "resource   acquisition   is   initialization"   technique   leads   to   less   code   than   use   of   a   "finally"   construct.    
  Also,   have   a   look   at   the   examples   of   resource   management   in   Appendix   E   of   The   C++   Programming   Language.    
   
   
   
  Top

18 楼james_razor(蹬三轮的)回复于 2001-08-31 16:12:15 得分 0

就是就是,C++提供了,为什么不用。xiterator之言深得吾心。  
  还有,回复的功能有个设计缺陷,明明排好的程序,发出去后tab就没了,全部在一排,nnd。zdg看到没有,看到了就麻烦你请改一改,谢谢。Top

19 楼cnss(飞碟)回复于 2001-08-31 16:26:42 得分 0

听课Top

20 楼binglex()回复于 2001-09-03 11:07:04 得分 0

这个帖子是不是有问题了,怎么散完分了,没有显示呢??Top

相关问题

  • 异常抛出
  • 类中异常抛出的问题?
  • main方法中能抛出异常吗?
  • 不抛出异常?
  • socket抛出异常
  • CoUninitialize抛出异常
  • 程序中抛出异常是否影响效率?
  • 关于抛出异常
  • JSF抛出java.lang.NullPointerException异常
  • weblogic抛出异常问题

关键词

  • 编译器
  • 内存
  • 系统
  • 抛出
  • 异常
  • 调用
  • 释放
  • 问题
  • delete
  • catch

得分解答快速导航

  • 帖主:james_razor
  • onetwothree
  • ed9er
  • binglex
  • xiterator

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

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