Smart pointers' control block internal machinery

I'm wondering what are the exact conditions to release memory allocated for the internal control block shared by shared_ptr and weak_ptr. I guess control block contains a shared_ptr counter and a weak_ptr counter.

#include <memory>
#include <iostream>

struct Dummy
{
    Dummy() { std::cout << "ctor" << std::endl; }
    ~Dummy() { std::cout << "dtor" << std::endl; }
};

int main()
{
    auto dummy = new Dummy();
    auto wp = std::weak_ptr<Dummy>(); // pointing to nothing

    {
        auto sp = std::shared_ptr<Dummy>(dummy); // 1
        wp = sp; // 2
    } // 3
    std::cout << "Land mark" << std::endl;
}
  1. Building a shared_ptr with dummy allocated memory. Control block is allocated, and it's Dummy pointer is set to "dummy"
  2. Building a weak_ptr from shared_ptr. Both smart pointers are sharing the same address of control block.
  3. Shared pointer is destroyed. Dummy dtor is called ("dtor" is printed before "Land mark"). Control block still lives until end of program.

Am I right about these comments ? What happens (in details) within control block during these steps ?

Edit: What happens with make_shared case ? There is one allocation containing Dummy object and control block. Does this involve placement new to use two differents objets ? Or is it a structure containing a raw object ?

#include <memory>
#include <iostream>

struct Dummy
{
    Dummy() { std::cout << "ctor" << std::endl; }
    ~Dummy() { std::cout << "dtor" << std::endl; }
};

int main()
{
    auto wp = std::weak_ptr<Dummy>(); // pointing to nothing
    {
        auto sp = std::make_shared<Dummy>();
        wp = sp;
    }
}

Answers


This is what valgrind massif shows for your test, ( if you are not used to valgrind ) this is the amount of memory allocated by time, first the pointed to object, then the count manager, and after that, the pointed to object is disallocated

This is basically how it works, when the last shared_ptr goes out of scope, the pointed to object is deleted (its memory disallocated), but the count manager is still there because the weak_ptr needs to know what is happening, if there is a pointed to object or not.

However sometimes this is not the case, if you use make_shared, make_shared uses actually only one allocation for both the object and the count manager, in this case, the memory allocated will stay there until the last weak_ptr goes out of scope


Yes, you are right.

Detail of what happens :

  1. The control block is created and bound to the share_ptr. shared_count = 1, weak_count = 0.
  2. The weak_pointer binds to the control block. shared_count = 1, weak_count = 1.
  3. The last (only) shared_pointer dies, destroying the object. The control block is maintained by the weak_ptr. shared_count = 0, weak_count = 1.
  4. (end of main()) The last (only) weak_ptr dies, and shared_count = 0. No one is bound to the control block anymore, so the last weak_ptr destroys the control block.

Need Your Help

Java rest server : make a unit test

java rest unit-testing

I try to make a unit test for a standalone rest server. If I run the rest server it work nice. But I don't know how to make the UnitTest running.