How to get the number of bytes actually occupied by a string in memory?

As far as I know, in C ++ there is an implementation-dependent optimization stringthat allows you stringnot to allocate any additional heap memory to store your characters, but rather to store the characters in the object itself string, therefore, if a line sallocates additional memory on the heap, the total consumed its memory is sizeof(string) + s.capacity(), however, if it does not allocate any additional memory on the heap, i.e. stores its characters in the object string, then the total memory consumption is sizeof(string).

Is there a way to determine this amount - the total memory consumed by the string? The problem is that I don’t see a way to find out if a string object allocates memory in a heap or not, so I don’t know which formula to use for a specific one string.

EDIT: A hack injecting something in the STL namespace to find out implementation-specific details (the threshold at which stringadditional memory starts to be allocated) will be fine if there is no other solution.

+4
source share
4 answers

Since it s.data()points to the first character of a string, you can check whether this address is inside the string object itself.

, , , . , , , , .

:

bool data_is_inline(const std::string & s)
{
    const char * p = reinterpret_cast<const char *>(&s), * q = s.data();
    for (std::size_t i = 0; i != sizeof(s); ++i)
        if (p + i == q) return true;
    return false;
}
+2

malloc :: operator new . .

size_t before = getTotalAllocated();
std::string str("Hello!");
size_t after = getTotalAllocated();
size_t diff = afer - before;

sizeof (std::string) diff,

+1

, s , sizeof(string) + s.capacity(), , , , sizeof(string).

, , ( Linux/GCC libstdc++ Windows...). ( ) sizeof(string) + s.capacity() (, std::string ).

AFAIK, "" "", .

std::string , - -

+1

, GCC.

, , realloc free.

: malloc

#include <malloc.h>
#include <iostream>

using namespace std;

static void my_init_hook (void);
static void *my_malloc_hook (size_t, const void *);
void* (* old_malloc_hook)(size_t size, const void *caller);
void (* volatile  __malloc_initialize_hook) (void) = my_init_hook;

static void my_init_hook (void)
{
  old_malloc_hook = __malloc_hook;
  __malloc_hook = my_malloc_hook;
}

size_t g_counter = 0;

static void * my_malloc_hook (size_t size, const void *caller)
{
    g_counter += size;
    __malloc_hook = old_malloc_hook;
    cout << "Allocated: " << size << endl;
    void* result =  malloc(size);
    __malloc_hook = my_malloc_hook;
}

int main()
{
    cout << "*** On stack ***" << endl;
    string a("12345");
    string b("1234567890");
    string c("12345678901234567890123456789012345678901234567890");
    string d(c);
    d[1] = 'A'; // this makes big allocation!
    cout << "*** On heap ***" << endl;
    string* x = new string("1234567890");
    string* y = new string(*x);
    string* z = new string(*x);
    cout << "Total allocation:" << g_counter << endl; 
}

:

*** On stack ***
Allocated: 18
Allocated: 23
Allocated: 63
Allocated: 63
*** On heap ***
Allocated: 4
Allocated: 23
Allocated: 4
Allocated: 4
Total allocation:202

, d[1] = 'A'; 63 .

This can be improved to calculate the distribution that occurs only from a particular caller, for example. a string allocator or make statistics on the distribution of the caller. I bought something similar a long time ago to find out who selects the lines, but I used the method of unwinding the stack.

+1
source

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


All Articles