Cpp

shared_ptr memory layout

Struct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class __shared_ptr {
element_type* _M_ptr; // Contained pointer.
__shared_count<_Lp> _M_refcount; // Reference counter.
}
class __shared_count {
_Sp_counted_base<_Lp>* _M_pi;
}


class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>

class _Sp_counted_base {

_Atomic_word _M_use_count; // #shared
_Atomic_word _M_weak_count; // #weak + (#shared != 0)

};

template<typename _Ptr, _Lock_policy _Lp>
class _Sp_counted_ptr final : public _Sp_counted_base<_Lp> {
_Ptr _M_ptr;
}

1. std::make_shared Function

Source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// memory.cpp
#include <memory>
#include <vector>
#include <iostream>

using VecUL = std::vector<unsigned long>;

void func(std::shared_ptr<VecUL> datas) {
auto count = datas.use_count();
std::cout << count << "\n";
for (auto &data : *datas) {
data++;
}
}

void func(std::shared_ptr<unsigned int> data) {
auto count = data.use_count();
std::cout << count << "\n";
}

int main() {
std::shared_ptr<unsigned int> ptr = std::make_shared<unsigned int>();
auto count = ptr.use_count();
std::cout << count << "\n";
*ptr = 65535;
func(ptr);

std::shared_ptr<VecUL> ptr1 = std::make_shared<VecUL>();
auto count1 = ptr1.use_count();
std::cout << count1 << "\n";
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
func(ptr1);

return 0;
}

Debug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
> g++ -g -O1 memory.cpp -o memory
> gdb memory

(gdb) br func
Breakpoint 1 at 0x12e9: func. (2 locations)
(gdb) run

(gdb) x /3gx $rdi
# element_type* # _Sp_counted_base<_Lp>*
0x7fffffffdaa0: 0x000055555556aec0 0x000055555556aeb0
0x7fffffffdab0: 0x00007ffff7dc2fc8

(gdb) x /2gx 0x000055555556aec0
# Contained
0x55555556aec0: 0x000000000000ffff 0x0000000000000411

(gdb) x /4gx 0x000055555556aeb0 # _Sp_counted_base<_Lp>*
# vtable pointer #_M_weak_count #_M_use_count
0x55555556aeb0: 0x0000555555557c78 0x0000000100000002
# Contained
0x55555556aec0: 0x000000000000ffff 0x0000000000000411
(gdb) c
Continuing.

(gdb) x /2gx $rdi
# element_type* # _Sp_counted_base<_Lp>*
0x7fffffffdaa0: 0x000055555556b2f0 0x000055555556b2e0
(gdb) x /4gx 0x000055555556b2f0
# vector Contained
0x55555556b2f0: 0x000055555556b380 0x000055555556b3a8
0x55555556b300: 0x000055555556b3c0 0x0000000000000021
(gdb) x /6gx 0x000055555556b380 # vector data
0x55555556b380: 0x000000000000ffff 0x000000000000ffff
0x55555556b390: 0x000000000000ffff 0x000000000000ffff
0x55555556b3a0: 0x000000000000ffff 0x0000000000000000

(gdb) x /6gx 0x000055555556b2e0 # _Sp_counted_base<_Lp>*
# _Sp_counted_ptr_inplace
# vtable pointer #_M_weak_count #_M_use_count
0x55555556b2e0: 0x0000555555557cb0 0x0000000100000002
# Contained
0x55555556b2f0: 0x000055555556b380 0x000055555556b3a8
0x55555556b300: 0x000055555556b3c0 0x0000000000000021

2. shared_ptr( Y* ptr ) Constructor

Source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <memory>
#include <vector>
#include <iostream>

using VecUL = std::vector<unsigned long>;

void func(std::shared_ptr<VecUL> datas) {
auto count = datas.use_count();
std::cout << count << "\n";
for (auto &data : *datas) {
data++;
}
}

void func(std::shared_ptr<unsigned int> data) {
auto count = data.use_count();
std::cout << count << "\n";
}

int main() {
auto * p0 = new unsigned int{34};
std::shared_ptr<unsigned int> ptr{p0};
auto count = ptr.use_count();
std::cout << count << "\n";
*ptr = 65535;
func(ptr);

auto *p1 = new VecUL{0xff, 0xffff, 0xffffff, 0xffffffff};
std::shared_ptr<VecUL> ptr1{p1};
auto count1 = ptr1.use_count();
std::cout << count1 << "\n";
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
ptr1->push_back(65535);
func(ptr1);

return 0;
}

Debug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
> g++ -g -O1 memory.cpp -o memory
> gdb memory

(gdb) br func
Breakpoint 1 at 0x1329: func. (2 locations)
(gdb) run
Breakpoint 1, func (data=std::shared_ptr<unsigned int> (use count 2, weak count 0) = {...}) at memory1.cpp:15

(gdb) x /2gx $rdi
0x7fffffffda90: 0x000055555556aeb0 0x000055555556aed0
(gdb) x /2gx 0x000055555556aeb0
0x55555556aeb0: 0x000000000000ffff 0x0000000000000000
(gdb) x /4gx 0x000055555556aed0 # _Sp_counted_base<_Lp>*
# _Sp_counted_ptr
# vtable pointer #_M_weak_count #_M_use_count
0x55555556aed0: 0x0000555555557c68 0x0000000100000002
# Contained pointer
0x55555556aee0: 0x000055555556aeb0 0x0000000000000411

(gdb) c
Continuing.

(gdb) x /2gx $rdi
0x7fffffffda90: 0x000055555556b300 0x000055555556b350

(gdb) x /4gx 0x000055555556b300
0x55555556b300: 0x000055555556b3c0 0x000055555556b408
0x55555556b310: 0x000055555556b440 0x0000000000000031
(gdb) x /6gx 0x000055555556b3c0
0x55555556b3c0: 0x00000000000000ff 0x000000000000ffff
0x55555556b3d0: 0x0000000000ffffff 0x00000000ffffffff
0x55555556b3e0: 0x000000000000ffff 0x000000000000ffff
(gdb) x /4gx 0x000055555556b350 # _Sp_counted_base<_Lp>*
# _Sp_counted_ptr
# vtable pointer #_M_weak_count #_M_use_count
0x55555556b350: 0x0000555555557ca0 0x0000000100000002
0x55555556b360: 0x000055555556b300 0x0000000000000051

Share