处理new分配内存失败情况
转自:http://www.51testing.com/html/70/n-827070.html
在C++语言中,我们经常会使用new给一个对象分配内存空间,而当内存不够会出现内存不足的情况。C++提供了两中报告方式:
1、抛出bad_alloc异常来报告分配失败;
2、返回空指针,而不会抛出异常。
C++为什么会采用这两种方式呢?这主要是由于各大编译器公司设计C++编译器公司的结果,因为标准C++是提供了异常机制的。例如,VC++6.0中当new分配内存失败时会返回空指针,而不会抛出异常。而gcc的编译器对于C++标准支持比较好,所以当new分配内存失败时会抛出异常。
究竟为什么会出现这种情况呢?
首先,C++是在C语言的基础之上发展而来,而且C++发明时是想尽可能的与C语言兼容。而C语言是一种没有异常机制的语言,所以C++应该会提供一种没有异常机制的new分配内存失败报告机制;(确实是如此,早期的C++还没有加入异常机制)
其次在返回空指针的实现过程中,C++采用的是malloc/calloc 等分配内存的函数,该类函数不会抛出异常,但是在分配内存失败时会返回“空指针”。
最后,对于标准的C++,有着比较完善的异常处理机制,所以对于出现异常时,会抛出响应的异常。对于new分配失败时,系统会抛出bad_alloc异常。
鉴于以上原因,我们在不同的编译器需要new分配失败时做不同的处理。例如:
情况1:
| int* p = new int(5); if ( p == 0 ) // 检查 p 是否空指针 return -1; ... |
情况2:
| try { int* p = new int(5); // 其它代码 } catch ( const bad_alloc& e ) { return -1; } |
情况1和情况2的代码都是对于new失败时的处理,而针对不同的编译器,可以这种处理会完全失效。如果在gcc编译器采用情况1,那么if(p==0)完全是没有意义的,因为不管new内存分配成功失败与否,都不会出现p=0的情况。即,如果分配成功,p=0完全不可能;而分配失败,new会抛出异常跳过其后面的代码。而需要采用情况2的处理方式,即应该来捕捉异常。
同样,如果在VC++6.0中采用情况2的代码,那么new分配失败时,完全不会抛出异常,那么捕捉异常也是徒劳的。
所以在new分配内存的异常处理时要特别小心,可以两种方式联合使用,来解决跨平台跨编译器的难题。
当然情况2中的异常处理代码是最简单的处理方式,下面我们为其制定一个客户制定的错误处理函数,即new-handler。
| typedef void (*new_handler)(); new_handler set_new_handler(new_handler p) throw(); |
这里首先定义new-handler函数指针类型,然后定义一个new-handler函数set_new_handler,其参数是指向operator new无法分配足够内存时应该被调用的函数。其返回指也是一个指针,指向set_new_handler被调用前正在执行(但是马上就要被替换)的那个new-handler函数。下面设计一个当operator new无法分配足够内存时应该被调用的函数:
|
void noMemoryToAlloc() std::abort(); |
使用noMemoryToAlloc函数的代码为:
|
int main() ... } |
当operator new无法分配足够空间时,noMemoryToAlloc就会被调用,于是程序就会发出一个错误信息cerr之后,调用abort函数结束程序。
如果operator new无法分配足够空间时,我们希望不断调用new-handler函数,直到找到足够内存为止,那么我们的operator new函数就可以设计为:
| void *operator new(std::size_t size) throw(std::bad_alloc) { if ( size==0 ) { size = 1; } while (true) { 调用malloc等内存分配函数来尝试分配size大小的内存; if ( 分配成功 ) return 指向分配得来的内存指针; new_handler globalHandler = set_new_handler(0); set_new_handle(globalHandler); if(globalHandler) (*globalHandler)(); else throw std::bad_alloc(); } } |
转自:http://blog.sina.com.cn/s/blog_9f1c09310101953s.html
使用new分配内存失败时往往会使用asert()终止程序,但是这只能在除错模式下abert函数才能有效,在生产模式下,abert只是一个void指令,所以连程序都跳不出来。
处理new分配内存失败情况的更多相关文章
- C++内存管理5-处理new分配内存失败情况(转)
C++内存管理5-处理new分配内存失败情况(转) endl; 参考博客: https://www.cnblogs.com/findumars/p/9905195.html
- C++new失败的处理(如果 new 分配内存失败,默认是抛出异常的,但也可以取消异常)
我们都知道,使用 malloc/calloc 等分配内存的函数时,一定要检查其返回值是否为“空指针”(亦即检查分配内存的操作是否成功),这是良好的编程习惯,也是编写可靠程序所必需的.但是,如果你简单地 ...
- malloc函数分配内存失败的常见原因
malloc()函数分配内存失败的常见原因: 1. 内存不足. 2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏.下次再使用malloc()函数申请内存 ...
- 在内存充足时malloc函数分配内存失败的原因及解决
昨天在修改自己的代码的时候,碰到了malloc函数内存分配失败,上网翻了翻,一个很可能的原因是之前的代码出现了越界操作,导致malloc分配函数所涉及的一些信息被破坏.在这个思想的指导下,今天又是郁闷 ...
- Unix系统编程()在堆上分配内存
在堆上分配内存:malloc和free 一般情况下,C程序使用malloc函数族在堆上分配和释放内存.较之brk和sbrk,这些函数具备不少优点: 属于C语言标准的一部分 更易于在多线程程序中使用 接 ...
- 浅析C++内存分配与释放操作过程——三种方式可以分配内存new operator, operator new,placement new
引言:C++中总共有三种方式可以分配内存,new operator, operator new,placement new. 一,new operator 这就是我们最常使用的 new 操作符.查看汇 ...
- du: fts_read 失败: 无法分配内存
今天在查看一个大的文件时突然报出一个du: fts_read 失败: 无法分配内存的错误. 用 ulimit -a 查看下 core file size (blocks, -c) 0 data seg ...
- linux设备驱动归纳总结(五):1.在内核空间分配内存【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-79134.html linux设备驱动归纳总结(五):1.在内核空间分配内存 xxxxxxxxxxxx ...
- c语言中-----分配内存函数
原型: void * realloc(void *p, size_t size); realloc 可以对给定的指针所指的空间进行扩大 或者 缩小, 原有内存的数据保持不变.当然,对于缩小,则缩小部 ...
随机推荐
- 在网页中引用DWG控件,交互绘图,和响应鼠标点击对象的方法
在网页中引用DWG控件,交互绘图,和响应鼠标点击对象的方法 [MXDRAW CAD控件文档] 下面帮助的完整例子,在控件安装目录的Sample\Ie\iedemo.htm中. 1. 主要用到 ...
- 学习笔记——网络编程3(基于TCP协议的网络编程)
TCP协议基础 IP协议是Internet上使用的一个关键协议,它的全称是Internet Protocol,即Internet协议,通常简称IP协议. 使用ServerSocket创建TCP服务 ...
- videojs
<link href="http://vjs.zencdn.net/5.5.3/video-js.css" rel="stylesheet"> &l ...
- C++ 类的初始化列表
class Animal{public: Animal(int weight,int height): //A初始化列表 m_weight(weight), m_height(height) { } ...
- 洛谷——P1549 棋盘问题(2)
P1549 棋盘问题(2) 搜索||打表 #include<cstdio> #include<cstring> #include<iostream> #includ ...
- [Algorithm] 3. Digit Counts
Description Count the number of k's between 0 and n. k can be 0 - 9. Example if n = 12, k = 1 in [0, ...
- HDU_5783_DivideTheSequence
HDU_5783_DivideTheSequence 点击打开链接 题意: 生成尽量多的连续的子串,且子串的前缀和大于等于0,输出符合题意的子串的数量. 这题目是参加四月份的个人训练赛遇到的,挺水的 ...
- Linux:RHEL7图形界面转文字
1.7 Systemd初始化进程 Linux操作系统开机过程首先从BIOS开始→进入"Boot Loader"→加载系统内核→内核进行初始化→启动初始化进程.初始化进程作为系统第一 ...
- Divide Groups 二分图的判定
Divide Groups Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- 九度oj 题目1089:数字反转
题目1089:数字反转 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3531 解决:1935 题目描述: 12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,现在又任 ...