How to Avoid Memory Leak with Shared_Ptr

How to avoid memory leak with shared_ptr?

If you have circular references like this, one object should hold a weak_ptr to the other, not a shared_ptr.

From the shared_ptr introduction:

Because the implementation uses reference counting, cycles of shared_ptr instances will not be reclaimed. For example, if main() holds a shared_ptr to A, which directly or indirectly holds a shared_ptr back to A, A's use count will be 2. Destruction of the original shared_ptr will leave A dangling with a use count of 1. Use weak_ptr to "break cycles."

Thanks, Glen, for the link.

Possible 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.

If yes how will that be possible ?

Smart pointers based on reference counting (such as shared_ptr) will delete the pointed-to-object when the reference count associated with the object drops to zero. But if you have a cycle in your references (A->B->A, or some more elaborate cycle), then the reference counts in the cycle will never drop to zero because the smart pointers are "keeping each other alive".

Here is an example of a simple program that leaks memory despite using only using shared_ptr for its pointers. Note that when you run it, the constructors print a message but the destructors never do:

#include <stdio.h>
#include <memory>

using namespace std;

class C
{
public:
C() {printf("Constructor for C: this=%p\n", this);}
~C() {printf("Destructor for C: this=%p\n", this);}

void setSharedPointer(shared_ptr<C> p) {pC = p;}

private:
shared_ptr<C> pC;
};

int main(int argc, char ** argv)
{
shared_ptr<C> pC(new C);
shared_ptr<C> pD(new C);

pC->setSharedPointer(pD);
pD->setSharedPointer(pC);

return 0;
}

How to prevent memory leaks in code that uses std::shared_ptr

How to prevent memory leaks in code that uses std::shared_ptr

Avoid raw new and delete. Always use std::unique_ptr or std::shared_ptr when you need an owning pointer. Use raw pointers only as non-owning handles. Use std::make_shared and std::make_unique to create objects that are owned by smart pointers. Don't call .release() on unique_ptrs. That's pretty much it.

std::shared_ptr(s) and memory leaks

I would just like to provide answer to this question myself.

Firstly thank you to those who commented and provided information.

When using std::shared_ptr<T>, the issues is manually calling _CrtDumpMemoryLeaks() what you need to do is use the flag _CRTDBG_CHECK_ALWAYS_DF which automatically checks for memory leaks right at the end of running.

The code i ended up using is:

    // detect memory leaks
#if defined(DEBUG) | defined(_DEBUG)
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) | _CRTDBG_CHECK_ALWAYS_DF); // added in _CRTDBG_CHECK_ALWAYS_DF
_CrtSetBreakAlloc(0);
#endif

Hope this helps those in the future :)

Valgrind indicates memory leak with shared_ptr c++11

To answer your questions:

  1. You make use allocate_shared to allow the use of a custom memory allocator. The signature is identical, except it takes a const reference to an allocator as the first argument.

  2. Although you may clean up the internals of LinkedListData, you never delete the allocated pointer in your cleanup method. cleanup should be called from the LinkedListData destructor, and you should use the regular deleter (or a custom deleter if using a custom allocator) to call delete on the LinkedListData pointer.

In short, this line will always lead to a memory leak:

LinkedList() : d(new LinkedListData<T>(), LinkedListData<T>::cleanup){}

How to avoid memory leak with shared_ptr and SWIG

Your example is missing two parts to get the destructor to run:

  1. Since SWIG knows absolutely nothing about std::ofstream the default behaviour is to do nothing beyond pass an opaque handle around. See another answer of mine for a further discussion of this.

    The fix here is to supply an empty definition for std::ofstream in your interface file to convince SWIG it knows enough to do more, even if you don't plan on exposing any members.

  2. SWIG needs to see the typedef itself - inside the %{ %} it just gets passed straight to the output module, not used in the wraping itself.

Thus your example becomes:

%module ptrtest

%include "boost_shared_ptr.i"
%include "std_string.i"

%shared_ptr( std::ofstream )

namespace std {
class ofstream {
};
}

%{
#include <fstream>
#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}
%}

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;
ofstream_ptr mk_out(const std::string& fname );

%pythoncode %{
def leak_memory():
ostr=mk_out('/tmp/dont_do_this.txt')
%}

For future reference you can avoid duplication of stuff that lives only in the .i file with %inline:

%inline %{
typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}
%}

Which declares, defines and wraps it all in one shot.

Is it necessary to avoid memory leak when returning pointer by using shared_ptr?

Instead of managing a raw pointer, or even a shared_ptr to manage a char pointer, you can simply use std::vector.

It has a constructor that accepts a size and a value (thus you don't need memset). You can use std::vector::data to access the underlying data buffer.

Below you can see an example for str. A similar solution can be applied to wstr.

#include <vector>

std::vector<char> str(len + 1, 0); // allocate size and set all elements to 0
//----------------------------------------vvvvvvvvvv
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str.data(), len, NULL, NULL);

Note:

In general it could be more straightforward using std::string. But until C++17 std::string::data returns a const char* which is incompatible with the Win32 API pointer which is used to write data into.
You can still return std::string from your G2U function, by using:

return std::string(str.begin(), str.end());

If you can use C++17 you can use std::string instead of std::vector<char> and then you will be able to return str directly.

Update:

Regarding the "P.S." at the end of your question - as far as I know the c language has no mechanism for automatic heap memory management.

Reassign a shared pointer with operator = causes memory leak?

After your edits, no there's no leaks. The memory allocated for the int with the value 400 will simply be deleted for you in the assignment.

C++ shared_ptr inheritance memory leak

There was a dataRead std::function in UserAgent which ended up getting set to a lambda containing a std::shared_ptr to itself stopping it self form destructing. I added a close() method and set the std::function to it default value.

Now all is well and it delete fine

Thanks for all your help any way



Related Topics



Leave a reply



Submit