在 C ++ How to program中有一段说:
一种常见的编程实践是分配动态内存,将该内存的地址分配给一个指针,使用指针来操作内存,并在不再需要内存时使用 delete 释放内存。如果在成功分配内存之后但在 delete 语句执行之前发生异常,则可能发生内存泄漏。C++ 标准在 header 中提供了类模板 unique_ptr 来处理这种情况。
任何人都可以向我介绍一个发生异常并且内存会像这篇文章那样泄漏的真实例子吗?
在 C ++ How to program中有一段说:
一种常见的编程实践是分配动态内存,将该内存的地址分配给一个指针,使用指针来操作内存,并在不再需要内存时使用 delete 释放内存。如果在成功分配内存之后但在 delete 语句执行之前发生异常,则可能发生内存泄漏。C++ 标准在 header 中提供了类模板 unique_ptr 来处理这种情况。
任何人都可以向我介绍一个发生异常并且内存会像这篇文章那样泄漏的真实例子吗?
一个更微妙的例子。
采用一个包含两个动态分配数组的类的简单实现:
struct Foo {
private:
int* first;
int* second;
public:
Foo()
: first(new int[10000])
, second(new int[10000])
{ }
void Bar() { throw 42; }
~Foo()
{
delete [] first;
delete [] second;
}
};
int main()
{
Foo f;
/* more code */
}
现在,如果我们因为在某处调用方法而得到异常,那么一切都很好 - 调用了析构函数Bar
的堆栈展开保证。f
但是如果我们bad_alloc
在初始化时得到一个,我们就会泄露指向second
的内存。first
class MyClass
{
public:
char* buffer;
MyClass(bool throwException)
{
buffer = new char[1024];
if(throwException)
throw std::runtime_error("MyClass::MyClass() failed");
}
~MyClass()
{
delete[] buffer;
}
};
int main()
{
// Memory leak, if an exception is thrown before a delete
MyClass* ptr = new MyClass(false);
throw std::runtime_error("<any error>");
delete ptr;
}
int main()
{
// Memory leak due to a missing call to MyClass()::~MyClass()
// in case MyClass()::MyClass() throws an exception.
MyClass instance = MyClass(true);
}
void func()
{
char *p = new char[10];
some_function_which_may_throw(p);
delete [] p;
}
如果调用some_function_which_may_throw(p)
抛出异常,我们会泄漏 . 指向的内存p
。
简单的例子
try {
int* pValue = new int();
if (someCondition) {
throw 42;
}
delete pValue;
} catch (int&) {
}
举一个不那么做作的例子,我最近在使用给定的分配器对象分配节点时在我的代码中发现了这种潜在的泄漏。
std::unique_ptr<node,alloc_aware> allocate_new_node(allocator& al, const value_type^ v) {
char* buffer = al.allocate(sizeof(node)); //allocate memory
return std::unique_ptr<node>(al.construct(buffer, v),{al})); //construct
}
由于缓冲区的原因,如何解决这个问题不太明显,但在帮助下我得到了它:
struct only_deallocate {
allocator* a;
size_type s;
only_deallocate(allocator& alloc, size_type size):a(&alloc), s(size) {}
template<class T> void operator()(T* ptr) {a->deallocate(ptr, s);}
operator alloc_aware() const {return alloc_aware(*a, s);}
};
std::unique_ptr<node,alloc_aware> allocate_new_node(allocator& al, const value_type& v) {
std::unique_ptr<node, only_deallocate> buf(alloc.allocate(sizeof(node)),{alloc, sizeof(node)});//allocate memory
alloc.construct(buf.get(), value);
return std::unique_ptr<node,alloc_aware>(std::move(buf));
}