Layout of std::string (libstdc++)

Source code

#include <string>

int main()
{
    std::string s = "Hello World";
    const char* cs = s.c_str();
    return 0;
}

Analysis

$ g++ --version
g++ (Ubuntu 13.2.0-4ubuntu3) 13.2.0
$ g++ main.cpp -g
$ gdb a.out
(gdb) b 7
(gdb) r
(gdb) disable pretty-printer
(gdb) p /x s
$1 = {
    _M_dataplus = {..., _M_p = 0x7fffffffde30},
    _M_string_length = 0xb,
    {_M_local_buf = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f,
                     0x72, 0x6c, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0},
     _M_allocated_capacity = 0x6f57206f6c6c6548}}
(gdb) p sizeof(s)
$2 = 32
(gdb) x/4xg &s
0x7fffffffde20:	0x00007fffffffde30	0x000000000000000b
0x7fffffffde30:	0x6f57206f6c6c6548	0x0000000000646c72
(gdb) x/1s s._M_dataplus._M_p
0x7fffffffde30:	"Hello World"
(gdb) x/1s cs
0x7fffffffde30:	"Hello World"

Here the payload is on the stack (small string optimization), but if ‘_M_string_length’ is greater than 15 it will be on the heap. (Source: gcc/libstdc++-v3/include/bits/basic_string.h)

The std::string payload is null-terminated (‘\0’). This seems to be useless, cause std::string stores the length, but it’s done to provide a null-terminated const char* via its method c_str().


Size comparison

char* std::string (len ≤ 15) std::string (len > 15)
Raw Ptr (to first char)1
+ Heap buffer (payload)
= 4 Byte + Payload
Raw Ptr (to first char)1
+ Length (of payload)2
+ Stack buffer (payload)3
= 32 Byte
Raw Ptr (to first char)1
+ Length (of payload)2
+ Stack buffer (capacity)3
+ Heap buffer (payload)
= 32 Byte + Payload

On 64 Bit: 1 8 Byte, 2 8 Byte, 3 16 Byte