【问题标题】:Weird memory leak in Visual Studio C++ projectVisual Studio C++ 项目中奇怪的内存泄漏
【发布时间】:2015-05-31 00:52:54
【问题描述】:

我使用unique_ptr。为了创建这个指针,我使用这个代码 sn-p:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); //line 44
}

我在built-in memory leak checker 的帮助下测试我的项目是否存在内存泄漏。

我得到以下结果:

Detected memory leaks!
Dumping objects ->
my_header.h(44) : {228} normal block at 0x008AD568, 8 bytes long.
 Data: <        > A0 CB 8A 00 01 00 00 00 
my_header.h(44) : {226} normal block at 0x008AD5B8, 8 bytes long.
 Data: <        > 00 D6 8A 00 00 00 00 00 
/////////////////this error repeats many times

另外,我使用deleaker。这个工具说,没有内存泄漏。

【问题讨论】:

  • 不要将它用于数组类型?
  • @KerrekSB,我在我的项目中使用了 make_unique 3 次。 make_unique 总是创建原始指针。我看到了这段代码 - stackoverflow.com/a/13512344/1756750 我的错误也用这段代码重现了。
  • 使用returnunique_ptr 会自动调用move -- 我认为这就是你想要的吗?
  • @erip,不幸的是,我不使用returnunique_ptr。我只是创建 unique_ptr 并调用 release().
  • @erip 从技术上讲,它不会调用std::move

标签: c++ c++11 visual-studio-2013 memory-leaks


【解决方案1】:

您不应该使用release(),除非您将指针原始文件交给其他人(希望是另一个std::unique_ptrstd::shared_ptr 等)。相反,您应该使用 reset(),或者只是让 scope-exit 为您销毁托管对象。

使用你的代码的最简单的例子来展示好坏:

不好:使用release()

#include <memory>

namespace
{
    template<typename T, typename ...Args>
    std::unique_ptr<T> make_unique(Args&& ...args)
    {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }
}

int main()
{
    std::unique_ptr<int> ptr = make_unique<int>(5);
    ptr.release();
}

Valgrind 输出

==29012== 4 bytes in 1 blocks are definitely lost in loss record 1 of 87
==29012==    at 0x10003B51B: malloc (vg_replace_malloc.c:303)
==29012==    by 0x1001CD43D: operator new(unsigned long) (in /usr/lib/libc++.1.dylib)
==29012==    by 0x10000147B: std::__1::unique_ptr<int, std::__1::default_delete<int> > (anonymous namespace)::make_unique<int, int>(int&&) (in ./Sample C++)
==29012==    by 0x100001337: main (in ./Sample C++)
==29012== 
==29012== LEAK SUMMARY:
==29012==    definitely lost: 4 bytes in 1 blocks
==29012==    indirectly lost: 0 bytes in 0 blocks
==29012==      possibly lost: 0 bytes in 0 blocks
==29012==    still reachable: 192 bytes in 6 blocks
==29012==         suppressed: 35,164 bytes in 435 blocks
==29012== Reachable blocks (those to which a pointer was found) are not shown.
==29012== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==29012== 
==29012== For counts of detected and suppressed errors, rerun with: -v
==29012== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 17)

好:使用reset()

#include <memory>

namespace
{
    template<typename T, typename ...Args>
    std::unique_ptr<T> make_unique(Args&& ...args)
    {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }
}

int main()
{
    std::unique_ptr<int> ptr = make_unique<int>(5);
    ptr.reset(); // HERE
}

Valgrind 输出

==29045== HEAP SUMMARY:
==29045==     in use at exit: 35,356 bytes in 441 blocks
==29045==   total heap usage: 508 allocs, 67 frees, 41,216 bytes allocated
==29045== 
==29045== LEAK SUMMARY:
==29045==    definitely lost: 0 bytes in 0 blocks
==29045==    indirectly lost: 0 bytes in 0 blocks
==29045==      possibly lost: 0 bytes in 0 blocks
==29045==    still reachable: 192 bytes in 6 blocks
==29045==         suppressed: 35,164 bytes in 435 blocks
==29045== Reachable blocks (those to which a pointer was found) are not shown.
==29045== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==29045== 
==29045== For counts of detected and suppressed errors, rerun with: -v
==29045== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 17)

只需完全删除main() 中的第二行即可收到与上述相同的输出(Good)。

int main()
{
    std::unique_ptr<int> ptr = make_unique<int>(5);
}

同样如此:

int main()
{
    std::unique_ptr<int> ptr = make_unique<int>(5);
    std::unique_ptr<int> other(ptr.release());
}

祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-06
    • 2015-05-09
    • 2021-03-28
    • 2020-12-19
    • 2011-04-01
    • 2012-03-07
    • 2013-05-18
    相关资源
    最近更新 更多