如何获取内存中字符串实际占用的字节数?

时间:2015-11-20 09:20:16

标签: c++ string memory optimization stl

据我所知,C ++中存在依赖于实现的string优化,它允许string不分配任何额外的堆内存来存储其字符,而是将字符存储在{ {1}}对象本身。因此,如果字符串string在堆上分配额外的内存,则它消耗的总内存为s,但是,如果它没有在堆上分配任何额外的内存,即将其字符存储在{{ 1}} object,然后总内存消耗为sizeof(string) + s.capacity()

有没有办法找出这个数量 - 字符串消耗的总内存?问题是我没有找到一种方法来确定字符串对象是否在堆上分配了内存,所以我不知道哪个公式用于某个string

编辑:如果没有其他解决方案,那么在STL名称空间中注入一些东西以找出依赖于实现的细节(sizeof(string)开始分配额外内存的阈值)将是正常的。

4 个答案:

答案 0 :(得分:2)

由于s.data()指向字符串的第一个字符,您可以检查该地址是否位于字符串对象本身内。

确保仅使用相等比较,因为指向不是同一完整对象的子对象的对象的指针没有指定的顺序。此外,您不能使用指针算法,只允许指针指向给定数组,并且您事先不知道数据指针是否位于字符串对象内。

例如:

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;
}

答案 1 :(得分:1)

您可以重载全局 malloc 函数和 :: operator new ,并将请求的大小添加到某个全局变量中。然后,您可以在创建或修改字符串之前和之后减去总分配计数。

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

如果您愿意,可以将sizeof(std :: string)添加到diff

答案 2 :(得分:1)

  

因此,如果字符串s在堆上分配额外的内存,则它消耗的总内存为sizeof(string) + s.capacity(),但是,如果它没有在堆上分配任何额外的内存,即将其字符存储在字符串对象,然后总内存消耗为sizeof(string)

我相信如果不深入了解实现的具体细节(Linux / GCC libstdc++和Windows上的不同......),我无法做出区分。并且标准不需要(即使非常可能)只在不良情况下花费sizeof(string) + s.capacity()(可能一些std::string实现可能会花费更多内存。)

AFAIK,许多实现与&#34;短&#34;的处理方式不同字符串和&#34; long&#34;其中,阈值是特定于实现的细节。

该标准不禁止std::string使用某些自己的特定分配器,执行某些hash consing - 即使这不太可能 - 或者其他

答案 3 :(得分:1)

此代码显示如何使用分配挂钩来测量GCC编译器的字符串分配。

请注意,还有其他一些可能很有趣的问题,例如reallocfree

以下是参考:Hooks for 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个字节的分配。

这可以改进以计算仅来自特定呼叫者的分配,例如,字符串分配器或由调用者进行分配统计。很久以前,我发现类似的东西,以找出谁在分配字符串,但我使用了展开堆栈的方法。