Why does the implementation of Microsoft std :: string require 40 bytes in the stack?

Having recently watched this video about the string implementation on facebook, I was curious to see the insides of the Microsoft implementation. Unfortunately, the string file (in %VisualStudioDirectory%/VC/include) does not seem to contain the actual definition, but rather just conversion functions (like atoi) and some operator overloads.

I decided to make some attempts and push it from programs at the user level. The first thing I did, of course, was to check sizeof(std::string). To my surprise, std :: string takes 40 bytes! (On 64-bit machines, anyway.) The previously mentioned video details how the facebook implementation only needs 24 bytes and gcc only 32 bytes, so that was shocking, to say the least.

We can go a little deeper by writing a simple program that prints the contents of the bytes byte (including the address of c_str) as such:

#include <iostream>
#include <string>
int main()
{
    std::string test = "this is a very, very, very long string";

    // Print contents of std::string test.
    char* data = reinterpret_cast<char*>(&test);
    for (size_t wordNum = 0; wordNum < sizeof(std::string); wordNum = wordNum + sizeof(uint64_t))
    {
        for (size_t i = 0; i < sizeof(uint64_t); i++)
            std::cout << (int)(data[wordNum + i]) << " ";

        std::cout << std::endl;
    }

    // Print the value of the address returned by test.c_str().
    // (Doing this byte-by-byte to match the above values).
    const char* testAddr = test.c_str();
    char* dataAddr = reinterpret_cast<char*>(&testAddr);

    std::cout << "c_str address: ";
    for (size_t i = 0; i < sizeof(const char*); i++)
        std::cout << (int)(dataAddr[i]) << " ";

    std::cout << std::endl;
}

This produces:

48 33 -99 -47 -55 1 0 0
16 78 -100 -47 -55 1 0 0
-52 -52 -52 -52 -52 -52 -52 -52
38 0 0 0 0 0 0 0
47 0 0 0 0 0 0 0
c_str address: 16 78 -100 -47 -55 1 0 0

, , , , - ( ), - , - . ? , , ? ?

, SSO ( ​​ "Short String" ). , :

0 36 -28 19 123 1 0 0
83 104 111 114 116 32 83 116
114 105 110 103 0 -52 -52 -52
12 0 0 0 0 0 0 0
15 0 0 0 0 0 0 0
c_str address: 112 -9 79 -108 23 0 0 0

EDIT: , , , , std::string 32 , . - , , .

: Yuushi , , Debug Iterator. , Debug Iterator ( ), std::string 32 , .

, , Debug Iterator Support .

+4
1

Visual Studio 2015 xstring string std::basic_string

.. VS2015, VS2013 , .

:

template<class _Elem,
class _Traits,
class _Alloc>
class basic_string
    : public _String_alloc<_String_base_types<_Elem, _Alloc> >
{
// This class has no member data
}

_String_alloc _Compressed_pair<_Alty, _String_val<_Val_types> > , std::string, _Alty std::allocator<char> _Val_types is _Simple_types<char>, std::is_empty<std::allocator<char>>::value true, sizeof _Compressed_pair<_Alty, _String_val<_Val_types> > is sizeof _String_val<_Val_types>

class _String_val _Container_base, typedef of _Container_base0, #if _ITERATOR_DEBUG_LEVEL == 0 _Container_base12 . _Container_base12 _Container_proxy . , _String_val :

union _Bxty
    {   // storage for small buffer or pointer to larger one
    _Bxty()
        {   // user-provided, for fancy pointers
        }

    ~_Bxty() _NOEXCEPT
        {   // user-provided, for fancy pointers
        }

    value_type _Buf[_BUF_SIZE];
    pointer _Ptr;
    char _Alias[_BUF_SIZE]; // to permit aliasing
    } _Bx;

size_type _Mysize;  // current length of string
size_type _Myres;   // current storage reserved for string

_BUF_SIZE 16.

pointer_type, size_type . .

, _ITERATOR_DEBUG_LEVEL == 0, sizeof std::string:

_BUF_SIZE + 2 * sizeof size_type

sizeof pointer_type +  _BUF_SIZE + 2 * sizeof size_type
+2

Source: https://habr.com/ru/post/1659683/


All Articles