gpt4 book ai didi

c++ - 解决将对象传递给抛出的函数时可能发生的内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 20:44:08 25 4
gpt4 key购买 nike

考虑这样一种情况,函数 foo(MyClass* mc) 应该将 mc 的拷贝保留到内部数据结构中,并保证该对象在不再使用时将被删除。

void foo(MyClass* mc) // acquires ownership of mc; may throw
{
// code that may throw
bar(mc); // acquires mc; may also throw
}

当此函数执行可能抛出的代码(例如,OutOfMemory 异常)时,就会出现问题。如果在将指针保存到数据结构之前引发异常,则显然应该在函数展开之前释放对象,因为调用者不再对此负责(调用者甚至不知道指针是否实际保存在数据结构)。

可以使用 RAII 通过范围保护来处理这个问题,但它看起来非常笨拙,并且会产生一些开销(它必须在每个获取指针的函数中完成)。

是否真的需要在每次获取动态分配的对象时都这样做,还是有更简洁的方法来做到这一点?!

template <class T>
struct VerifyAcq {
T* ptr;
bool done;
VerifyAcq(T* ptr):ptr(ptr) { done = false; }
~VerifyAcq() {
if (!done) delete ptr;
}
};

void foo(MyClass* mc) // acquires mc; may throw
{
VerifyAcq<MyClass> va(mc);
// code that may throw
bar(mc); // acquires mc; may throw; must implement the same mechanism!
va.done = true;
}
// Note: there might be no public way of "undoing" what bar has done (no rollbak)
// and even if there was, what if it could also throw?...

调用者不能为了删除指针而捕获异常,因为在抛出异常之前,函数可能已经成功地将指针添加到数据结构中,释放对象会使数据结构不健全(悬挂指针).

最佳答案

当我开始阅读代码时,我停在了这里:

void foo(MyClass* mc) // acquires ownership of mc; may throw

评论不是记录所有权获取的最佳方式。最好的方法是使用类型系统。

 void foo(std::unique_ptr<MyClass> mc) // no comment required

修复接口(interface)也最终解决了问题。

(如果您的标准库中没有 unique_ptr,则有替代方案,例如 Howard Hinnant's emulation in C++03)。

关于c++ - 解决将对象传递给抛出的函数时可能发生的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13744426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com