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?
解决方法
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?”
该标准保证在构造期间抛出异常时将自动释放分配有“新表达式”的内存.
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?”