{"id":9362,"date":"2020-12-11T09:44:22","date_gmt":"2020-12-11T09:44:22","guid":{"rendered":"http:\/\/www.max-sperling.bplaced.net\/?p=9362"},"modified":"2024-03-27T11:37:35","modified_gmt":"2024-03-27T11:37:35","slug":"stdshared_ptr-in-memory","status":"publish","type":"post","link":"http:\/\/www.max-sperling.bplaced.net\/?p=9362","title":{"rendered":"Layout of std::shared_ptr (libstdc++)"},"content":{"rendered":"<p><strong>Source code<\/strong><\/p>\n<pre class=\"brush: cpp; title: main.cpp; notranslate\" title=\"main.cpp\">\r\n#include &lt;memory&gt;\r\n  \r\nint main()\r\n{\r\n  std::shared_ptr&lt;int&gt; sPtr1 = std::make_shared&lt;int&gt;(42);\r\n  std::shared_ptr&lt;int&gt; sPtr2 = sPtr1;\r\n  return 0;\r\n}\r\n<\/pre>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\n$ g++ --version\r\ng++ (Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0\r\n\r\n$ g++ main.cpp -std=c++11 -g\r\n<\/pre>\n<hr>\n<p><strong>Debugging<\/strong><\/p>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\n$ gdb a.out\r\n(gdb) b 7\r\n(gdb) r\r\nBreakpoint 1, main () at main.cpp:7\r\n7\t  return 0;\r\n\r\n\/\/ Shared pointer with Pretty printer\r\n(gdb) enable pretty-printer\r\n163 printers enabled\r\n163 of 163 printers enabled\r\n(gdb) p sPtr1\r\n$1 = std::shared_ptr&lt;int&gt; (use count 2, weak count 0) = {get() = 0x615c30}\r\n(gdb) p sPtr2\r\n$2 = std::shared_ptr&lt;int&gt; (use count 2, weak count 0) = {get() = 0x615c30}\r\n\r\n\/\/ Shared pointer without Pretty printer\r\n(gdb) disable pretty-printer\r\n163 printers disabled\r\n0 of 163 printers enabled\r\n(gdb) p sPtr1\r\n$3 = {&lt;std::__shared_ptr&lt;int, (__gnu_cxx::_Lock_policy)2&gt;&gt; = {&lt;std::__shared_ptr_access&lt;int, (__gnu_cxx::_Lock_policy)2, false, false&gt;&gt; = {&lt;No data fields&gt;}, _M_ptr = 0x615c30, _M_refcount = {_M_pi = 0x615c20}}, &lt;No data fields&gt;}\r\n(gdb) p sPtr2\r\n$4 = {&lt;std::__shared_ptr&lt;int, (__gnu_cxx::_Lock_policy)2&gt;&gt; = {&lt;std::__shared_ptr_access&lt;int, (__gnu_cxx::_Lock_policy)2, false, false&gt;&gt; = {&lt;No data fields&gt;}, _M_ptr = 0x615c30, _M_refcount = {_M_pi = 0x615c20}}, &lt;No data fields&gt;}\r\n\r\n(gdb) p &amp;sPtr1\r\n$5 = (std::shared_ptr&lt;int&gt; *) 0x7fffffffdca0\r\n(gdb) p sizeof(sPtr1)\r\n$6 = 16\r\n(gdb) p &amp;sPtr2\r\n$7 = (std::shared_ptr&lt;int&gt; *) 0x7fffffffdcb0\r\n(gdb) p sizeof(sPtr2)\r\n$8 = 16\r\n\r\n\/\/ Object (The same behind sPtr1 and sPtr2)\r\n(gdb) p *sPtr1._M_ptr\r\n$9 = 42\r\n(gdb) p sizeof(*sPtr1._M_ptr)\r\n$10 = 4\r\n\r\n\/\/ Control block (The same behind sPtr1 and sPtr2)\r\n(gdb) p *sPtr1._M_refcount._M_pi\r\n$11 = {&lt;std::_Mutex_base&lt;(__gnu_cxx::_Lock_policy)2&gt;&gt; = {&lt;No data fields&gt;}, _vptr._Sp_counted_base = 0x401970 &lt;vtable for std::_Sp_counted_ptr_inplace&lt;int, std::allocator&lt;int&gt;, (__gnu_cxx::_Lock_policy)2&gt;+16&gt;, _M_use_count = 2, _M_weak_count = 1}\r\n(gdb) p sizeof(*sPtr1._M_refcount._M_pi)\r\n$12 = 16\r\n\r\n\/\/ Both shared_ptr (Stack)\r\n(gdb) x\/4x 0x7fffffffdca0\r\n0x7fffffffdca0:\t0x00615c30\t0x00000000\t0x00615c20\t0x00000000\r\n(gdb) x\/4x 0x7fffffffdcb0\r\n0x7fffffffdcb0:\t0x00615c30\t0x00000000\t0x00615c20\t0x00000000\r\n\r\n\/\/ Object (Heap)\r\n(gdb) x\/d 0x00615c30\r\n0x615c30:\t42\r\n\r\n\/\/ Control block (Heap)\r\n(gdb) x\/4x 0x00615c20\r\n0x615c20:\t0x00401970\t0x00000000\t0x00000002\t0x00000001\r\n(gdb) info symbol 0x401970\r\nvtable for std::_Sp_counted_ptr_inplace&lt;int, std::allocator&lt;int&gt;, (__gnu_cxx::_Lock_policy)2&gt; + 16 in section .rodata of \/&lt;path_to_binary&gt;\/a.out\r\n<\/pre>\n<hr>\n<p><strong>Visual result<\/strong><\/p>\n<pre>\r\n|----------------------|\r\n|   shared_ptr sPtr1   |\r\n|----------------------|\r\n|Pointer to the Object |---|-------> Object\r\n|                      |   |           (Int value 42)\r\n|Pointer to the Ctr blk|---|---|\r\n|----------------------|   |   |---> Ctl block\r\n                           |   |       (Pointer to allocator, deleter, ...)\r\n|----------------------|   |   |       (Shared reference counter)\r\n|   shared_ptr sPtr2   |   |   |       (Weak reference counter + offset 1)\r\n|----------------------|   |   |\r\n|Pointer to the Object |---|   |\r\n|                      |       |\r\n|Pointer to the Ctr blk|-------|\r\n|----------------------|\r\n<\/pre>\n<pre>\r\n                         Stack (Frame 0)\r\n                      ---------------------\r\n      0x7fffffffdcb8: 0x00615c20 0x00000000 (Ctl block)\r\nsPtr2 0x7fffffffdcb0: 0x00615c30 0x00000000 (Object)\r\n      0x7fffffffdca8: 0x00615c20 0x00000000 (Ctl block)\r\nsPtr1 0x7fffffffdca0: 0x00615c30 0x00000000 (Object)\r\n                      ---------------------\r\n                               \u2193\r\n\r\n                               \u2191\r\n                              Heap\r\n                      ---------------------\r\nObj   0x000000615c30: 0x0000002a 0x00000000 (Int value 42)\r\n      0x000000615c2c: 0x00000001            (Weak reference counter + offset 1)\r\n      0x000000615c28: 0x00000002            (Shared reference counter)\r\nC Blk 0x000000615c20: 0x00401970 0x00000000 (Pointer to allocator, deleter, ...)\r\n                      ---------------------\r\n<\/pre>\n<hr>\n<p><strong>Insides<\/strong><\/p>\n<p>If you create the shared pointer not with std::make_shared but with an explicit new the object and the control block are stored at two different memory locations. The control block contains then an additional pointer to the object.<\/p>\n<p>When the shared\/strong reference counter reaches zero the object gets destroyed. Afterwards only if the weak reference counter is\/reaches zero the control block gets destroyed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source code Debugging Visual result |&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-| | shared_ptr sPtr1 | |&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-| |Pointer to the Object |&#8212;|&#8212;&#8212;-> Object | | |<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false},"categories":[80,28,64],"tags":[],"_links":{"self":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/9362"}],"collection":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9362"}],"version-history":[{"count":2,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/9362\/revisions"}],"predecessor-version":[{"id":17258,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/9362\/revisions\/17258"}],"wp:attachment":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9362"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}