在内存不足的情况下使用带异常处理的STL容器 我在代码中使用STL容器(用Visual Studio 2010在C++中开发) 我以前从未对STL容器使用过异常处理。由于STL容器抛出bad_alloc异常,我计划在示例代码中使用like,如下所示。让我们假设function()在内存不足的情况下被调用
现在,我不确定这是完整的验证代码还是我需要做任何额外的清理活动在内存不足的情况下使用带异常处理的STL容器 我在代码中使用STL容器(用Visual Studio 2010在C++中开发) 我以前从未对STL容器使用过异常处理。由于STL容器抛出bad_alloc异常,我计划在示例代码中使用like,如下所示。让我们假设function()在内存不足的情况下被调用,c++,visual-studio-2010,stl,C++,Visual Studio 2010,Stl,现在,我不确定这是完整的验证代码还是我需要做任何额外的清理活动 class MyClass { std::vector<int>* integer_vector; public: MyClass() { std::string message; message += "my message"; // bad_alloc could be thrown from here
class MyClass
{
std::vector<int>* integer_vector;
public:
MyClass()
{
std::string message;
message += "my message"; // bad_alloc could be thrown from here
integer_vector = new std::vector<int>; // bad_alloc could be thrown from here
}
};
void function()
{
try
{
MyClass* myclass_ptr;
myclass_ptr = new (std::nothrow) MyClass;
if (myclass_ptr==NULL)
{
// ANY CLEANUP NEEDED HERE ?
return;
}
std::map<int, char> myintcharmap; // bad_alloc could be thrown from here
}
catch(...)
{
// ANY CLEANUP NEEDED HERE ?
return;
}
}
class-MyClass
{
std::vector*整数向量;
公众:
MyClass()
{
std::字符串消息;
message+=“我的消息”;//可以从这里抛出错误的alloc
integer\u vector=new std::vector;//可以从此处抛出错误的\u alloc
}
};
空函数()
{
尝试
{
MyClass*MyClass_ptr;
myclass_ptr=新(std::nothrow)myclass;
if(myclass_ptr==NULL)
{
//这里需要清理吗?
返回;
}
std::map myintcharmap;//可以从这里抛出错误的\u alloc
}
捕获(…)
{
//这里需要清理吗?
返回;
}
}
请有人看一下并提供帮助。您显示的代码中有两个主要的潜在漏洞。可以说,这两种方法都源于使用原始指针。您应该更喜欢使用
std::unique_ptr
(如果您有C++11)或其他类似的“智能”指针来指示所有权,并且通常是为了异常安全。现代指南是避免几乎所有的new
或delete
;当它们无法避免时,它们需要配对。请注意,您的代码有两次调用new
,但没有调用delete
在函数
中,核心问题是您可能会完全分配myclass_ptr
所拥有的数据,在以后的分配中导致异常,然后由于myclass_ptr
不再在范围内,因此无法清理它
假设您已修复该问题,因此如果在创建MyClass
实例后发生异常,它将清理该实例。您的代码仍然会泄漏,因为在MyClass
中,integer\u vector
当前存在类似的问题。虽然您可以按照三的规则编写一个析构函数来处理这种情况,但是在这里使用智能指针可能更容易
异常处理是一个更大、更固执己见的话题。我将留下一个总结,即捕获异常并挤压它们通常是不好的(通常这只在需要特定类型稳定性的程序的外部循环中是合法的)。在范围太窄以至于您不知道如何处理异常的情况下捕获异常通常也是不好的。(例如,
函数如何决定是否重试、放弃或使用另一种方法?它的调用者或链上的调用者可能拥有更多信息,并且处于更好的处理位置。)您显示的代码中有两个主要的潜在泄漏。可以说,这两种方法都源于使用原始指针。您应该更喜欢使用std::unique_ptr
(如果您有C++11)或其他类似的“智能”指针来指示所有权,并且通常是为了异常安全。现代指南是避免几乎所有的new
或delete
;当它们无法避免时,它们需要配对。请注意,您的代码有两次调用new
,但没有调用delete
在函数
中,核心问题是您可能会完全分配myclass_ptr
所拥有的数据,在以后的分配中导致异常,然后由于myclass_ptr
不再在范围内,因此无法清理它
假设您已修复该问题,因此如果在创建MyClass
实例后发生异常,它将清理该实例。您的代码仍然会泄漏,因为在MyClass
中,integer\u vector
当前存在类似的问题。虽然您可以按照三的规则编写一个析构函数来处理这种情况,但是在这里使用智能指针可能更容易
异常处理是一个更大、更固执己见的话题。我将留下一个总结,即捕获异常并挤压它们通常是不好的(通常这只在需要特定类型稳定性的程序的外部循环中是合法的)。在范围太窄以至于您不知道如何处理异常的情况下捕获异常通常也是不好的。(例如,函数如何决定是否重试、放弃或使用另一种方法?它的调用者,或链上更上层的调用者,可能拥有更多信息,并且处于更好的位置来处理此问题。)在大多数情况下,您不应该处理坏的所有异常。您的try/catch
以及if(myclass\u ptr==NULL)
都应该被删除
扪心自问:如果进程内存耗尽,我能做什么?最好的办法是记录一些东西,清理/释放系统资源,然后让程序终止。这是唯一正确的做法
您可以通过设置新的\u处理程序(使用set\u new\u处理程序)来实现这一点。如果内存分配失败,新操作员将调用它
std::set_new_handler(my_handler); // do your cleanup in 'my_handler'
在大多数情况下,您不应处理坏的所有异常。您的try/catch
以及if(myclass\u ptr==NULL)
都应该被删除
扪心自问:如果进程内存耗尽,我能做什么?最好的办法是记录一些东西,清理/释放系统资源,然后让程序终止。这是唯一正确的做法
您可以通过设置新的\u处理程序(使用set\u new\u处理程序)来实现这一点。如果内存分配失败,新操作员将调用它
std::set_new_handler(my_handler); // do your cleanup in 'my_handler'
您是否在询问您处理异常的策略是否正确,或者