C++中检查new是否成功分配内存
在练习性质的代码中,我们都假定 new 将返回一个指向内存块的有效指针。事实上,除非请求分配的内存量特大,或系统处于临界状态,可供使用的内存很少,否则 new 一般都能成功。有些应用程序需要请求分配大块的内存(如数据库应用程序),因此最好不要假定内存分配能够成功。 C++提供了两种确认指针有效的方法,默认方法是使用异常(这也是前面一直使用的方法),即如果内存分配失败,将引发 std::bad_alloc 异常。这导致应用程序中断执行,除非您提供了异常处理程序,否则应用程序将崩溃,并显示一条类似于“异常未处理”的消息。
以下示例程序演示了如何使用异常处理检查分配请求是否失败:
#include <iostream>
using namespace std;
// remove the try-catch block to see this application crash
int main()
{
try
{
// Request a LOT of memory!
int* pointsToManyNums = new int [0x1fffffff];
// Use the allocated memory
delete[] pointsToManyNums;
}
catch (bad_alloc)
{
cout << "Memory allocation failed. Ending program" << endl;
}
return 0;
}
输出:
Memory allocation failed. Ending program
分析:
在您的计算机上,这个程序的执行情况可能不同。在我的计算机上,无法为 536870911 个整型分配内存,如果没有编写异常处理程序(第 14~17 行的 catch 块),程序将以令人非常讨厌的方式结束。
要查看这个程序在没有异常处理程序时的行为,可将第 6、 7 和 13~17 行注释掉。使用 Microsoft Visual Studio 以调试模式生成可执行文件,并在 Microsoft Visual Studio 外部执行它时,将出现Debug Error! 的输出。
由此可知,当内存分配导致程序无法正常执行时, try-catch 异常处理结构让程序能够向用户指出这一点,再正常退出。
不想依赖于异常的程序员可使用 new 变种 new(nothrow), 这个变种在内存分配失败时不引发异常,而返回 NULL,让您能够在使用指针前检查其有效性,如以下示例程序所示:
#include <iostream>
using namespace std;
int main()
{
// Request LOTS of memory space, use nothrow
int* pointsToManyNums = new(nothrow) int [0x1fffffff];
if (pointsToManyNums) // check pointsToManyNums != NULL
{
// Use the allocated memory
delete[] pointsToManyNums;
}
else
cout << "Memory allocation failed. Ending program" << endl;
return 0;
}
输出:
Memory allocation failed. Ending program
分析:
这个程序与程序清单8.15相同, 但使用的是new(nothrow)。这个变种在分配内存失败时返回NULL,让我们能够在使用指针前检查其有效性,如第 8 行所示。这两种做法都可行,如何选择取决于您。