循环中的std :: unique_ptr - 内存泄漏

时间:2016-02-24 19:55:25

标签: c++ multithreading for-loop memory-leaks unique-ptr

unique_ptr是否按预期正确使用?代码以一些内存泄漏(可能是误报?或真正的泄漏?)结束。我想将所有权移到RunSimulation,其中unique_ptr的生命将结束,并且在循环中将创建更新的生命,但是,这将以访问冲突结束。

理想情况下,我希望main()中的一个unique_ptr对象在main()中到期,另一个在main外部发送,以便在RunSimulation()中释放。

class Result { public: int n; };

void RunSimulation(std::unique_ptr<Result> result) {result->n = 0;}

void main()
{
        boost::thread_group threads;

        std::unique_ptr<Result> r;
        std::unique_ptr<Simulation> sim = std::make_unique<Simulation>();

        for (int i = 0; i < 10; i++)
        {
            r = std::unique_ptr<Result>(new Result);

            //Erroneous lines:
            //threads.create_thread(boost::bind(&RunSimulation, std::move(r)));
            //threads.create_thread([&] {RunSimulation(std::move(r));  });
        }

        threads.join_all();
}

2 个答案:

答案 0 :(得分:2)

您没有内存泄漏,但这并不是说您的代码是正确的。看看你的循环:

all_keys = list()

... 
         all_keys += list(set(reader.fieldnames).difference(set(all_keys)))

每次将新的Result实例分配给r时,旧的Result实例都会被unique_ptr删除。这可能发生在其指针使用它的线程之前,在这种情况下,您尝试取消引用已删除的内存。这是未定义的行为。

<强>更新 这是一个例子

for (int i = 0; i < 10; i++)
{
    r = std::unique_ptr<Result>(new Result);
    threads.create_thread([&] { RunSimulation(r.get()); });
}

答案 1 :(得分:0)

  

在下面正确使用unique_ptr

没有

r指向的对象在连续迭代中被破坏,而它仍然可以在复制指针的线程中使用,从而导致未定义的行为。

  

代码以一些内存泄漏结束(可能是误报?

可能。在_CrtDumpMemoryLeaks被销毁之前调用r,因此内存尚未被释放。

  

我认为将所有权移至RunSimulation,其中unique_ptr的生命将结束

这是一个明智的想法。我建议这样做。

  然而,

以访问冲突结束。

那个程序可能也有错误。

    for (int i = 0; i < 10; i++)
    {
        r = std::unique_ptr<Result>(new Result);
        threads.create_thread([&] { RunGridSimulation(std::move(r)); });
    }

这个替代方案的问题(好的,同样的问题也在最初的替代方案中)是你捕获对局部变量的引用,但是在超出局部变量范围的线程中使用lambda。所有线程都将指向同一个变量,如果线程没有碰巧与循环完美交错,那么一个线程将从另一个线程已经移动的唯一指针移动,导致指针未定义时的行为解除引用。

您必须将唯一指针移动到lambda中,而不是通过引用捕获它。