我在我的代码中使用STL容器(使用Visual Studio 2010在C ++中开发)
我之前从未使用过STL容器的异常处理。由于STL容器抛出bad_alloc
异常,我计划使用如下所示的示例代码。假设在低内存情况下调用function()
。
现在,我不确定它是否是完整的验证码或者我是否需要进行任何额外的清理活动。
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;
}
}
请有人帮忙看看。
答案 0 :(得分:2)
您显示的代码中有两个主要的潜在泄漏。两者都可以说源于使用原始指针。您应该更喜欢使用std::unique_ptr
(如果您有C ++ 11)或其他类似的“智能”指针来指示所有权,以及一般的异常安全。现代指导是避免几乎所有new
或delete
的使用;当它们无法避免时,它们需要配对。请注意,您的代码只有两次调用new
,但没有调用delete
。
在function
内,核心问题是您可以完全分配myclass_ptr
“拥有”的数据,在以后的分配中导致异常,然后无法将其清除为{{1} }已不在范围内。
假设您修复了这个问题,以便在创建异常后清除myclass_ptr
实例。您的代码仍然会泄漏,因为在MyClass
内部,MyClass
目前存在类似的问题。虽然你可以遵循三条规则并编写一个析构函数来处理这种情况,但在这里使用智能指针可能更容易。
异常处理是一个更大,更有见解的主题。我将留下一个摘要,通常很难捕获异常并压缩它们(通常这只是在需要特定稳定性的程序的外循环中才合法)。在范围如此狭窄的情况下捕获异常通常也很糟糕,以至于您不知道如何处理它们。 (例如,integer_vector
将如何决定是再次尝试,放弃还是使用其他方法?它的调用者,或者链上的调用者可能拥有更多信息并处于更好的处理。)
答案 1 :(得分:2)
在大多数情况下,您不应该处理 bad_alloc例外。应删除try/catch
以及if (myclass_ptr==NULL)
。
问问自己:如果进程内存耗尽,我可以做些什么?你可以希望最好的事情是记录一些东西,清理/释放系统资源,让程序终止。这是唯一正确的做法。
您可以通过设置new_handler(使用set_new_handler)来完成此操作。如果内存分配失败,它将由new运算符调用。
std::set_new_handler(my_handler); // do your cleanup in 'my_handler'