Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ leaks in case of exception even by using smart pointers

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?

like image 783
efabor Avatar asked Apr 10 '12 14:04

efabor


People also ask

Can you have memory leaks with smart pointers?

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.

What problem does using smart pointers help prevent?

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.

Is Shared_ptr slow?

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.

What happens when Shared_ptr goes out of scope?

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.


3 Answers

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 before std::terminate() is called.

like image 131
Mike Seymour Avatar answered Oct 13 '22 05:10

Mike Seymour


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.

like image 23
modelnine Avatar answered Oct 13 '22 06:10

modelnine


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));
like image 41
Ram Avatar answered Oct 13 '22 06:10

Ram