Trying to understand the fields of std::_Sp_counted_base in gcc's bits/shared_ptr_base.h header file

39 views Asked by At

I'm reading the g++ implementations of std::shared_ptr and std::weak_ptr, and I cannot figure out why sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>) is not 8.

In bits/shared_ptr_base.h:

  1. std::shared_ptr<_Tp> derives from std::__shared_ptr<_Tp>.
  2. std::__shared_ptr<_Tp> has an element_type* and a __shared_count<_Lp>. _Lp represents a lock policy.
  3. std::__shared_count<_Lp> is a wrapper of std::_Sp_counted_base<_Lp>*.

Then:

  1. std::_Sp_counted_base<_Lp> derives from std::_Mutex_base<_Lp>. Since std::_Mutex_base<_Lp> is an empty base class when _Lp is not __gnu_cxx::_S_mutex and the default value is __gnu_cxx::_S_atomic, it will not contribute to std::_Sp_counted_base<_Lp>'s size in my case.
  2. There are only 2 fields in std::_Sp_counted_base<_Lp>'s definition: _M_use_count and _M_weak_count. They are both _Atomic_word, which is a type alias of int.
  3. So std::_Sp_counted_base<__gnu_cxx::__default_lock_policy> should be 8 bytes?

https://godbolt.org/z/8dK7G1ar1

#include <iostream>
#include <memory>
#include <iomanip>

template <typename... Ts>
void println(Ts &&... xs) {
    std::cout << std::boolalpha;
    ((std::cout << xs << " "), ...);
    std::cout << "\n";
}

int main() {
    static_assert(__gnu_cxx::__default_lock_policy == __gnu_cxx::_S_atomic);
    println("_Sp_counted_base   ", sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>));
    println("_Atomic_word       ", sizeof(_Atomic_word));
    println("_Mutex_base        ", sizeof(std::_Mutex_base<__gnu_cxx::_S_atomic>));
    println("_Sp_counted_base<a>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_atomic>));
    println("_Sp_counted_base<m>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_mutex>));
    println("_Sp_counted_base<s>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_single>));
}

I compiled the code with gcc 13.2. sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>)) is 16 in 64-bit mode and 12 in 32-bit mode. Is there a hidden long or pointer field that I missed? The source I'm reading is g++ 14.0.1, but even when I change the compiler version, the result stays the same.

0

There are 0 answers