C++中除了沿用C的alloc系列函数之外,还可以用new/new []来分配内存(这句是废话),我们在使用new这个operator的时候多是直接使用,而没有额外引用头文件。
写C语言代码写习惯的人都会在alloc函数之后,对指针做NULL判断,以检查内存分配是否成功,那么在C++中是否也需要以同样的方式来检查内存分配是否成功呢?根据实际code验证结果,答案是new成功返回即表示内存分配成功,不需检查指针是否为NULL,但是仍然会出现内存分配失败的情况,此时需要捕捉bad_alloc这种exceptin来知晓内存分配失败,bad_alloc是在new这个C++头文件(#include
1 #include <iostream>
2 #include <new>
3 #include <cstdlib>
4
5 using namespace std;
6
7 int main(int argc, char *arg[])
8 {
9 char *buffer = NULL;
10
11 try
12 {
13 buffer = new char[90000000000ul]; // 故意分配很大的一块内存,导致操作失败
14
15 cout<<"The buffer address is: "<<static_cast<void*>(buffer)<<endl;
16 }
17 catch (const bad_alloc &ex)
18 {
19 cout<<"exception: "<<ex.what()<<endl;
20 }
21 catch (...)
22 {
23 cout<<"unknown exception"<<endl;
24 }
25
26 if (NULL != buffer)
27 {
28 delete[] buffer;
29 }
30
31 return 0;
32 }
对上面的代码进行编译和运行,结果如下
Administrator@attention /e/Code
$ g++ stl_new.cpp -lstdc++ -o stl_new.exe
Administrator@attention /e/Code
$ ./stl_new.exe
exception: std::bad_alloc
Administrator@attention /e/Code
$
可以看出分配失败时,的确throw出了bad_alloc,代码catch到这个exception即可知道内存分配失败。细心看上面的代码是有#include
void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();
其中很明显new和new[]这两个operator都被声明会throw出std::bad_alloc(入参只有size的那种,后面均指这种,不重复说明),那是不是因为引用new头文件的缘故而使用了这个特定类型的new了呢?
经过实际代码验证,答案为“不是”,实际上代码里去掉#include
new这个operator是C++语言内置的,其本身在内存分配失败会throw出一个bad_alloc,因此我们在使用new进行内存/对象分配时,就必须使用catch来捕捉这种可能的bad_alloc来检查分配是否失败;若不做如此处理,被throw出来的bad_alloc会未在这一层被捕捉而一直向上冒泡,若我们的代码中一直不进行catch,则会一直冒泡到CRT,而CRT对这些未被捕捉异常,处理方式是调用abort()来直接结束整个程序,最终的后果便是程序异常退出。这里再罗嗦的贴一段代码来说明这一点
1 #include <stdio.h>
2
3 int main(int argc, char *argv[])
4 {
5 char *buffer = NULL;
6
7 buffer = new char[90000000000ul]; // 故意分配很大的一块内存
8 printf("The buffer address is: %p\n", buffer);
9
10 if (NULL != buffer)
11 {
12 delete[] buffer;
13 }
14
15 return 0;
16 }
最终编译和运行结果为
Administrator@attention /e/Code
$ ./new.exe
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
对此自己的感受便是,在C++代码中使用new,应该将其包括在try{}catch(){}中,以知道分配是否成功和避免未捕捉的异常而导致程序异常退出。
但实际实际上在非嵌入式的环境中,比如桌面环境,内存都比较充裕(加上操作系统虚拟内存机制),内存分配失败几乎是微乎其微,而导致很多的try{}catch(){}形同虚设,而使代码有些dirty。并且倘若真的是出现内存分配失败的问题,那多是意味着软已经出现了严重的错误(比如内存泄漏),就算在这里catch到本次分配失败,也对于整个系统恢复也没什么作用,因此很多代码里都是直接使用new,而没有将其包括在try{}catch(){}之中。
对此个人感觉是还是严谨的使用try{}catch(){}为好,毕竟内存分配失败了,也算是一种错误,应该即可就对此进行捕捉处理,将错误影响范围尽可能限制在出错的位置,这样避免错误扩大,也方便debug排错。
原文链接: https://www.cnblogs.com/lanyuliuyun/archive/2013/04/25/3041476.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/85873
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!