微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – std :: make_unique vs reset(新T)

我想问一个关于构造函数中的内存泄漏的问题.我们来考虑一个课程:
class Foo
 {
   public:
      Foo(){ throw 500;} 
 };

有什么区别

std::unique_ptr<Foo> l_ptr = std::make_unique<Foo>();

std::unique_ptr<Foo> l_ptr;
l_ptr.reset(new Foo());

在我看来,make_unique的解决方案应该保护我免受内存泄漏,但在这两种情况下我得到了相同的valgrind结果:

$valgrind --leak-check=full ./a.out
==17611== Memcheck,a memory error detector
==17611== copyright (C) 2002-2015,and GNU GPL'd,by Julian Seward et al.
==17611== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==17611== Command: ./a.out
==17611== 
terminate called after throwing an instance of 'int'
==17611== 
==17611== Process terminating with default action of signal 6 (SIGABRT)
==17611==    at 0x5407418: raise (raise.c:54)
==17611==    by 0x5409019: abort (abort.c:89)
==17611==    by 0x4EC984C: __gnu_cxx::__verbose_terminate_handler() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==17611==    by 0x4EC76B5: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==17611==    by 0x4EC7700: std::terminate() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==17611==    by 0x4EC7918: __cxa_throw (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==17611==    by 0x40097B: Foo::Foo() (in /home/rungo/Repositories/test/a.out)
==17611==    by 0x4008DC: main (in /home/rungo/Repositories/test/a.out)
==17611== 
==17611== HEAP SUMMARY:
==17611==     in use at exit: 72,837 bytes in 3 blocks
==17611==   total heap usage: 4 allocs,1 frees,72,841 bytes allocated
==17611== 
==17611== 132 bytes in 1 blocks are possibly lost in loss record 2 of 3
==17611==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17611==    by 0x4EC641F: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==17611==    by 0x400963: Foo::Foo() (in /home/rungo/Repositories/test/a.out)
==17611==    by 0x4008DC: main (in /home/rungo/Repositories/test/a.out)
==17611== 
==17611== LEAK SUMMARY:
==17611==    definitely lost: 0 bytes in 0 blocks
==17611==    indirectly lost: 0 bytes in 0 blocks
==17611==      possibly lost: 132 bytes in 1 blocks
==17611==    still reachable: 72,705 bytes in 2 blocks
==17611==         suppressed: 0 bytes in 0 blocks
==17611== Reachable blocks (those to which a pointer was found) are not shown.
==17611== To see them,rerun with: --leak-check=full --show-leak-kinds=all
==17611== 
==17611== For counts of detected and suppressed errors,rerun with: -v
==17611== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[1]    17611 abort (core dumped)  valgrind --leak-check=full ./a.out

当我使用clang和g时,它是一样的.
在这里找到:https://isocpp.org/wiki/faq/exceptions#ctors-can-throw这句话:

Note: if a constructor finishes by throwing an exception,the memory associated with the object itself is cleaned up — there is no memory leak.

我的问题是为什么我们在这种情况下有泄漏以及为什么make_unique不能防止泄漏(doeas意味着make_unique和reset(new …)之间没有dofference?

解决方法

你是否正在捕捉异常?捕获异常时,valgrind(使用g 6.2 -g编译)检测到make_unique和reset都没有泄漏.
int main() try
{
#if TEST_MAKE_UNIQUE
    std::unique_ptr<Foo> l_ptr = std::make_unique<Foo>();   
#else
    std::unique_ptr<Foo> l_ptr;
    l_ptr.reset(new Foo());
#endif
}
catch(...)
{

}

AddressSanitizer也不报告任何问题.

(P.S.这是展示鲜为人知的function-try-block语言功能的好机会.)

“Why doesn’t the memory get leaked?”

该标准保证在构造期间抛出异常时将自动释放分配有“新表达式”的内存.

From $15.2.5:

If the object was allocated by a new-expression ([expr.new]),the matching deallocation function ([basic.stc.dynamic.deallocation]),if any,is called to free the storage occupied by the object.

相关问题:

> “What happens to the memory allocated by new if the constructor throws?”
> “std::unique_ptr::reset and constructor exceptions”
> “Is it ever not safe to throw an exception in a constructor?”

原文地址:https://www.jb51.cc/c/114638.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐