VC中如何做才能让new失败时抛出一个std::bad_alloc异常?

soloist 2002-05-12 05:12:46
在标准C++中,new一个对象时如果分配内存失败就会抛出一个std::bad_alloc异常。如果希望new操作失败时不抛出异常而仅仅传回一个NULL指针,可以这样显式地调用:new(nothrow)。
现在有如下代码:
01 #include <new>
02 #include <iostream>
03
04 using namespace std; // std c++ libs implemented in std
05
06 class BigClass
07 {
08 public:
09 BigClass() {}
10 ~BigClass(){}
11 double BigArray[99999999];
12 };
13
14 void main()
15 {
16 try
17 {
18 BigClass * p = new BigClass;
19 }
20 catch( bad_alloc a)
21 {
22 const char * temp = a.what();
23 cout << temp << endl;
24 cout << "Threw a bad_alloc exception" << endl;
25 }
26
27 BigClass * q = new(nothrow) BigClass;
28 if ( q == NULL )
29 cout << "Returned a NULL pointer" << endl;
30
31 try
32 {
33 BigClass * r = new BigClass[3];
34 }
35 catch( bad_alloc a)
36 {
37 const char * temp = a.what();
38 cout << temp << endl;
39 cout << "Threw a bad_alloc exception" << endl;
40 }
41 }

标准C++的operator new操作符声明在<new>头文件中:
void *__cdecl operator new(size_t) _THROW1(std::bad_alloc);
void *__cdecl operator new(size_t, const std::nothrow_t&) _THROW0();

抛出异常的operator new定义在newop.cpp里,不抛出异常的operator new定义在newop2.cpp里。

以上代码在VC6.0中编译连接通过,但是在程序运行期间18行和33行new操作无论如何都不会抛出一个std::bad_alloc异常,而只是返回一个NULL指针。于是我跟踪进每一个new调用观察,发现18和33行的new实际上调用了new.cpp里的operator new,而这个operator new是不抛出异常的,所以在我的程序里就抓不到std::bad_alloc了。现在我不明白的是为什么程序不调用newop.cpp里的operator new?而27行的new(nothrow)则确实调用了newop2.cpp里的operator new,执行结果就是返回了一个NULL指针。

我要如何做才能在VC中让new失败时能够抛出一个std::bad_alloc异常?
...全文
652 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoluoli 2002-05-15
  • 打赏
  • 举报
回复
我试了试没有错!但有一个警告!,说的是你不能释放你分配的内存,应为你在程序结束时没有不你分配的内存用delete释放
anrxhzh 2002-05-15
  • 打赏
  • 举报
回复
This is a bug in Microsoft's implementation of operator new as this in not in conformance with the ANSI C++ Standard.


http://support.microsoft.com/default.aspx?scid=kb;EN-US;q167733
soloist 2002-05-15
  • 打赏
  • 举报
回复
#include <new>
#include <iostream>
using namespace std;

class BigClass
{
public:
BigClass() {}
~BigClass() {}
double array[99999999];
};

int main(int argc, char *argv[])
{
try
{
BigClass *p1 = new BigClass;
}
catch (bad_alloc)
{
cout << "new BigClass throw bad_alloc\n";
}

BigClass *p2 = new(nothrow) BigClass;
if (0 == p2)
cout << "new(nothrow) BigClass return NULL\n";

try
{
BigClass *p3 = new BigClass[3];
}
catch (bad_alloc)
{
cout <<"new BigClass[3] throw bad_alloc\n";
}

BigClass *p4 = new(nothrow) BigClass[3];
if (0 == p4)
cout << "new(nothrow) BigClass[3] return NULL\n";

return 0;
}

以上代码在DevC++ 4.9.3.0中编译通过,并执行,输出结果如下:
new BigClass throw bad_alloc
new(nothrow) BigClass return NULL
new BigClass[3] throw bad_alloc
new(nothrow) BigClass[3] return NULL
这说明new正确抛出异常了.这个版本的DevC++用的是G++ 2.95.3-6(mingw special)做后台编译器,看样子就这点来说G++ 对C++标准的支持比vc6.0好.我查阅了《Windows程序调试》,它确实是通过_set_new_handler让VC能抛出异常的。
但这毕竟是非标准的做法,因为标准C++是在handler被调用且返回0以后才会抛出异常的,而非直接在handler里抛出异常。
soloist 2002-05-14
  • 打赏
  • 举报
回复
我试过 set_new_handler(0),可是没有用.

而且我认为 _set_new_handler() 和是否抛异常无关,它只是让operator new分配内存失败时调用一个handler而已,在这个handler里可以再次尝试分配内存,但是还不成功的话就返回0,接着operator new继续执行,此时按照C++标准,operator new就应该抛出一个异常了.

其实operator new永远都调用new.cpp 里不抛异常的版本才是问题,也是我迷惑的地方.
huaxiaotao 2002-05-13
  • 打赏
  • 举报
回复
coppermine(coppermine)说得没错。
canco 2002-05-13
  • 打赏
  • 举报
回复
强烈推荐《Windows程序设计》,本书有答案。
http://www.csdn.net/expert/topic/694/694634.xml?temp=.937237
kof99th 2002-05-13
  • 打赏
  • 举报
回复
用set_new_handler(0),把错误处理函数置为空,自然会抛出std::bad_alloc异常了.呵呵.
coppermine 2002-05-12
  • 打赏
  • 举报
回复
可以 set_new_handler(0);来迫使new抛出异常.
soloist 2002-05-12
  • 打赏
  • 举报
回复
我的本意并不是要它成功分配,而是想试试看怎么样用,new失败时才会抛出一个异常.
lizsss 2002-05-12
  • 打赏
  • 举报
回复
assert只能判断是否正确分配

建议:直接用malloc
lizsss 2002-05-12
  • 打赏
  • 举报
回复
用assert可以替代new
soloist 2002-05-12
  • 打赏
  • 举报
回复
STL没有重载operator new,而且std名字空间中也没有operator new.
delphihero 2002-05-12
  • 打赏
  • 举报
回复
用using std
std::new() 试试不知道stl有没有重写 new

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧