C++new失败的处理(如果 new 分配内存失败,默认是抛出异常的,但也可以取消异常)
if ( p == 0 ) // 检查 p 是否空指针
return -1;
// 其它代码
其实,这里的 if ( p == 0 ) 完全是没啥意义的。C++ 里,如果 new 分配内存失败,默认是抛出异常的。所以,如果分配成功,p == 0 就绝对不会成立;而如果分配失败了,也不会执行 if ( p == 0 ),因为分配失败时,new 就会抛出异常跳过后面的代码。如果你想检查 new 是否成功,应该捕捉异常:
try {
int* p = new int[SIZE];
// 其它代码
} catch ( const bad_alloc& e ) {
return -1;
}
据说一些老的编译器里,new 如果分配内存失败,是不抛出异常的(大概是因为那时 C++ 还没加入异常机制),而是和 malloc 一样,返回空指针。不过我从来都没遇到过 new 返回空指针的情况。
当然,标准 C++ 亦提供了一个方法来抑制 new 抛出异常,而返回空指针:
int* p = new (std::nothrow) int; // 这样如果 new 失败了,就不会抛出异常,而是返回空指针
if ( p == 0 ) // 如此这般,这个判断就有意义了
return -1;
// 其它代码
===============================详解===================================
首先按c++标准的话,new失败会抛出bad_alloc异常,但是有些编译器对c++标准支持不是很好,比如vc++6.0中new失败不会抛出异常,而返回0.
//不支持c++标准的做法如下
double *ptr=new double[1000000];
if( 0 == ptr)
……处理失败……
//标准推荐做法一:
try
{
double *ptr=new double[1000000];
}
catch(bad_alloc &memExp)
{
//失败以后,要么abort要么重分配
cerr<<memExp.what()<<endl;
}
//标准推荐做法二:
是使用set_new_handler函数处理new失败。它在头文件<new>里大致是象下面这样定义的:
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
可以看到,new_handler是一个自定义的函数指针类型,它指向一个没有输入参数也没有返回值的函数。set_new_handler则是一个输入并返回new_handler类型的函数。
set_new_handler的输入参数是operator new分配内存失败时要调用的出错处理函数的指针,返回值是set_new_handler没调用之前就已经在起作用的旧的出错处理函数的指针。
可以象下面这样使用set_new_handler:
// function to call if operator new can't allocate enough memory
void nomorememory()
{
cerr << "unable to satisfy request for memory\n";
abort();
}
int main()
{
set_new_handler(nomorememory);
int *pbigdataarray = new int[100000000];
...
}
operator new不能满足内存分配请求时,new-handler函数不只调用一次,而是不断重复,直至找到足够的内存。实现重复调用的代码在条款8里可以看到,这里我用描述性的的语言来说明:一个设计得好的new-handler函数必须实现下面功能中的一种。
·产生更多的可用内存。这将使operator new下一次分配内存的尝试有可能获得成功。实施这一策略的一个方法是:在程序启动时分配一个大的内存块,然后在第一次调用new-handler时释放。释放时伴随着一些对用户的警告信息,如内存数量太少,下次请求可能会失败,除非又有更多的可用空间。
·安装另一个不同的new-handler函数。如果当前的new-handler函数不能产生更多的可用内存,可能它会知道另一个new-handler函数可以提供更多的资源。这样的话,当前的new-handler可以安装另一个new-handler来取代它(通过调用set_new_handler)。下一次operator new调用new-handler时,会使用最近安装的那个。(这一策略的另一个变通办法是让new-handler可以改变它自己的运行行为,那么下次调用时,它将做不同的事。方法是使new-handler可以修改那些影响它自身行为的静态或全局数据。)
·卸除new-handler。也就是传递空指针给set_new_handler。没有安装new-handler,operator new分配内存不成功时就会抛出一个标准的std::bad_alloc类型的异常。
·抛出std::bad_alloc或从std::bad_alloc继承的其他类型的异常。这样的异常不会被operator new捕捉,所以它们会被送到最初进行内存请求的地方。(抛出别的不同类型的异常会违反operator new异常规范。规范中的缺省行为是调用abort,所以new-handler要抛出一个异常时,一定要确信它是从std::bad_alloc继承来的。想更多地了解异常规范)
·没有返回。典型做法是调用abort或exit。abort/exit可以在标准c库中找到(还有标准c++库)。
上面的选择给了你实现new-handler函数极大的灵活性。
更多知识请参考《Effective c++》
https://blog.csdn.net/water_cow/article/details/20938075
C++new失败的处理(如果 new 分配内存失败,默认是抛出异常的,但也可以取消异常)的更多相关文章
- 处理new分配内存失败情况
转自:http://www.51testing.com/html/70/n-827070.html 在C++语言中,我们经常会使用new给一个对象分配内存空间,而当内存不够会出现内存不足的情况.C++ ...
- C++内存管理5-处理new分配内存失败情况(转)
C++内存管理5-处理new分配内存失败情况(转) endl; 参考博客: https://www.cnblogs.com/findumars/p/9905195.html
- malloc函数分配内存失败的常见原因
malloc()函数分配内存失败的常见原因: 1. 内存不足. 2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏.下次再使用malloc()函数申请内存 ...
- 在内存充足时malloc函数分配内存失败的原因及解决
昨天在修改自己的代码的时候,碰到了malloc函数内存分配失败,上网翻了翻,一个很可能的原因是之前的代码出现了越界操作,导致malloc分配函数所涉及的一些信息被破坏.在这个思想的指导下,今天又是郁闷 ...
- 浅析C++内存分配与释放操作过程——三种方式可以分配内存new operator, operator new,placement new
引言:C++中总共有三种方式可以分配内存,new operator, operator new,placement new. 一,new operator 这就是我们最常使用的 new 操作符.查看汇 ...
- Unix系统编程()在堆上分配内存
在堆上分配内存:malloc和free 一般情况下,C程序使用malloc函数族在堆上分配和释放内存.较之brk和sbrk,这些函数具备不少优点: 属于C语言标准的一部分 更易于在多线程程序中使用 接 ...
- 早期malloc分配时,如果内存耗尽分配不出来,会直接返回NULL。现在分配不出来,直接抛出异常(可使用nothrow关键字)
今天和同事review代码时,发现这样的一段代码: Manager * pManager = new Manager(); if(NULL == pManager) { //记录日志 return f ...
- du: fts_read 失败: 无法分配内存
今天在查看一个大的文件时突然报出一个du: fts_read 失败: 无法分配内存的错误. 用 ulimit -a 查看下 core file size (blocks, -c) 0 data seg ...
- 在dll里malloc/new/cvCreate分配内存,在exe里free/Releases释放内存时会出错。
写了个程序,在DLL中用malloc分配了一块内存,但是在exe程序中释放,结果程序crash,原因就是:其原因可能是堆被损坏,这也说明 TestMySticker.exe 中或它所加载的任何 DLL ...
随机推荐
- Oracle排名函数(Rank)实例详解
这篇文章主要介绍了Oracle排名函数(Rank)实例详解,需要的朋友可以参考下 --已知:两种排名方式(分区和不分区):使用和不使用partition --两种计算方式(连续,不连续),对应 ...
- <Linux> 下安装和卸载JDK
安装 下载jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 在local ...
- PHP 获取LDAP服务器Schema数据
最近工作中一直在与LDAP打交道,在官方推荐的client-apis里,可以很容易找到每个语言对应的API,进而与LDAP服务器交互.但是在用ApacheDirectoryStudio时,这个软件竟然 ...
- ResNet实战
目录 Res Block ResNet18 Out of memory # Resnet.py #!/usr/bin/env python # -*- coding:utf-8 -*- import ...
- POJ 1330 (LCA)
http://poj.org/problem?id=1330 题意:给出一个图,求两个点的最近公共祖先. sl :水题,贴个模板试试代码.本来是再敲HDU4757的中间发现要用LCA, 操蛋只好用这 ...
- 剑客决斗(NYOJ 110)
T3.题目110剑客决斗 (http://acm.nyist.net/JudgeOnline/problem.php?pid=110) 描述 在路易十三和红衣主教黎塞留当权的时代,发生了一场决斗.n个 ...
- 洛谷P1257 平面上的最接近点对
n<=10000个点,求欧几里德距离最小的一对点. 经典分治,把这些点按x排序,分成两半,每边分别算答案,答案是左边的最小,右边的最小,左右组起来的最小三者的最小.发现只有左右组的有点难写. 假 ...
- ci框架(codeigniter)Email发送邮件、收件人、附件、Email调试工具
ci框架(codeigniter)Email发送邮件.收件人.附件.Email调试工具 Email 类 CodeIgniter 拥有强大的 Email 类来提供如下的功能: 多 ...
- Codeforces 645C Enduring Exodus【二分】
题目链接: http://codeforces.com/contest/645/problem/C 题意: 给定01串,将k头牛和农夫放进, 0表示可以放进,1表示不可放进,求农夫距离其牛的最大距离的 ...
- 一个1x1px大小Data/Base64数据的gif透明图片
<img src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNg ...