C ++内存泄漏修复

时间:2013-08-14 15:23:10

标签: c++ pointers memory-leaks

我被要求优化c ++项目,并且我在类代码中遇到了这种“内存泄漏”情况(示例简化但主要问题很明显):

std::list<T*> _list;
void func(){
    T* obj = some_func();
    if (!obj){
        obj = new T();
        _list.push_back(obj); // Here is a leak,we do not know when *obj will be removed from _list to call its destructor 
    }
    obj->some_field = some_value; 
}
/*_list will be used and managed somewhere else 
  and we do not know actually when, where and how.*/

那怎么可以优雅地修复呢?优雅地,我的意思是没有定义我自己的容器。 我需要使用一些智能指针吗?

更新。这不是C ++ 11.所以没有花哨的有用的东西

5 个答案:

答案 0 :(得分:3)

  

那怎么可以优雅地修复呢?

尽可能存储对象,否则存储智能指针。通过哑指针进行内存管理是内存泄漏的一个因素,更糟糕的是。

std::unique_ptr将是最好的智能指针 - 它匹配单个所有者(列表)的语义,并具有转移和转出所有权的能力。但是,你说过去一直处于困境,所以最好的选择可能是来自TR1或Boost的shared_ptr

  

我是否需要使用一些智能指针?

这是迄今为止最简单的解决方案,假设您无法存储对象。另一种方法是仔细控制如何从列表中删除指针,确保您删除它们或以明确指定的方式转移所有权(并且新所有者正确地履行其职责)。你基本上是定义自己的容器适配器;虽然你可以使用现成的解决方案,比如Boost的指针容器。

答案 1 :(得分:0)

使用some_func的协议是什么?调用者是否应该获得返回对象的所有权?如果是这样,它将被泄露。假设列表取得对象的所有权,您需要将some_func返回的obj推送到列表中。实际上,在这里使用unique_ptrs将有助于使其更加清晰。

答案 2 :(得分:0)

假设您正在存储指向列表(std::list<T*> _list;)的指针,这可能会有所帮助:

namespace RAII
{
    template<typename T>
    class AUTO_LIST_WITH_POINTER
    {
    public:
        AUTO_LIST_WITH_POINTER(){}
        ~AUTO_LIST_WITH_POINTER()
        {
            // if you compiler does not support lambdas, replace this with
            // a simple 'for' loop
            std::for_each( list_.begin(), list_.end(), []( T * & listItem )throw()
            {
                delete listItem;
            } );
        }

        const std::list<T*> & get()const
        {
            return list_;
        }

        std::list<T*> & get()
        {
            return list_;
        }

        std::list<T*> detach() // Warning: probably an expensive operation!!!!
        {
            std::list<T*> list( list_ );
            list_.clear();
            return list;
        }

    private:
        std::list<T*> list_;

        AUTO_LIST_WITH_POINTER( const AUTO_LIST_WITH_POINTER & );             // TODO: don't implement, or..?? the OP should know better
        AUTO_LIST_WITH_POINTER & operator=( const AUTO_LIST_WITH_POINTER & ); // TODO: don't implement, or..?? the OP should know better
    };
}

答案 3 :(得分:0)

其中一个选择是使用RAII,依赖std::unique_ptr以及移动语义。例如:

std::list<std::unique_ptr<T>> list;
auto obj = some_func();
int some_value = 1;
if (!obj){
    std::unique_ptr<T> new_obj(new T());
    list.emplace_back(std::move(new_obj));
    obj = list.back().get();
}
obj->some_field = some_value;

答案 4 :(得分:0)

如果没有C ++ 11,您可以使用std::auto_ptr<>。这会将指针的所有权转移给一个所有者,因此如果_list的类型为std::list<std::auto_ptr<T>>,则在销毁容器时将删除这些对象。