I am new to the smart pointers world. I've done my reading and all of them stated that smart pointers will avoid leaking memory even when the program will exit after encountering an exception.
I wrote down a simple program to try this out, but Valgrind is telling me my program is leaking memory (three allocs and only one free).
This is the source code:
#include <iostream>
#include <memory>
using namespace std;
int main()
{
auto_ptr<int> ptr_int(new int(5));
throw std::bad_alloc();
cout << *ptr_int;
}
And this Valgrind report:
==27862== Memcheck, a memory error detector
==27862== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==27862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==27862== Command: ./smart_pointers
==27862== Parent PID: 5388
==27862==
==27862==
==27862== HEAP SUMMARY:
==27862== in use at exit: 104 bytes in 2 blocks
==27862== total heap usage: 3 allocs, 1 frees, 120 bytes allocated
==27862==
==27862== 4 bytes in 1 blocks are still reachable in loss record 1 of 2
==27862== at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255)
==27862== by 0x804878A: main (smart_pointers.cpp:8)
==27862==
==27862== 100 bytes in 1 blocks are possibly lost in loss record 2 of 2
==27862== at 0x4025BD3: malloc (vg_replace_malloc.c:236)
==27862== by 0x40E861A: __cxa_allocate_exception (in /usr/lib/libstdc++.so.6.0.14)
==27862== by 0x80487AE: main (smart_pointers.cpp:10)
==27862==
==27862== LEAK SUMMARY:
==27862== definitely lost: 0 bytes in 0 blocks
==27862== indirectly lost: 0 bytes in 0 blocks
==27862== possibly lost: 100 bytes in 1 blocks
==27862== still reachable: 4 bytes in 1 blocks
==27862== suppressed: 0 bytes in 0 blocks
==27862==
==27862== For counts of detected and suppressed errors, rerun with: -v
==27862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 19 from 8)
Does using smart pointers guarantee the allocated resources will be destroyed even if an exception shows up?
Even when using smart pointers, is it still possible to have memory leak ? Yes, if you are not careful to avoid creating a cycle in your references.
Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too.
shared_ptr are noticeably slower than raw pointers. That's why they should only be used if you actually need shared ownership semantics. Otherwise, there are several other smart pointer types available. scoped_ptr and auto_ptr (C++03) or unique_ptr (C++0x) both have their uses.
The smart pointer has an internal counter which is decreased each time that a std::shared_ptr , pointing to the same resource, goes out of scope – this technique is called reference counting. When the last shared pointer is destroyed, the counter goes to zero, and the memory is deallocated.
If an exception is not handled, then it's implementation-defined whether the stack will be unwound before calling std::terminate
.
If you handle the exception, then the smart pointer will work as expected.
Reference:
C++11 15.5.1 The std::terminate()
function
1 In some situations exception handling must be abandoned for less subtle error handling techniques. These situations are:
........
— when the exception handling mechanism cannot find a handler for a thrown exception , or
........
2 In such cases
std::terminate()
is called. In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound beforestd::terminate()
is called.
When std::terminate()
is called (as is the case for an uncaught exception), normal cleanup is not run (at least for the stack-frame of main()
), and as such the memory you've allocated in that stack frame leaks, even though it's supposedly managed by a smart-pointer. When you're catching the std::bad_alloc
in main()
, and return normally, the smart-pointer will do it's duty.
If the exception is not caught, then the stack unwinding is implementation specific. Therefore in your case, it does not release the memory.
Also, auto_ptr is no longer recommended.
Use std::unique_ptr :
unique_ptr<int> ptr_int(new int(5));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With