Vidrohi
Vidrohi

Reputation: 112

Two 'new' calls when creating std::string dynamically

I am trying to create a simple memory manager to get familiar with the concept, I have provided overrides for global new and delete and just started messing with constructing some objects when I noticed that for a single dynamic string allocation, I seem to hit new twice. The first time new gets hit, its even before the string constructor has been called and strangely, this is the larger of the two allocations, the second time it gets hit, the call comes from the std::string (basic_string) constructor.

I would like to know what the two new's are about. Specifically, I care about it in this context because every one of those new's creates its own allocation header and I have an academic curiosity in the kind of overhead I would be introducing if I used a simple memory manager.

Relevant code :

class DumbDataType
{
    std::string m_name;
};

int main()
{
    printf("STARTING MEMORY MANAGEMENT TESTING \n");

    printf("******************* Creating DATA ******************* \n");
    std::string* data = new std::string();
    delete data;

    printf("******************* Creating LORE ******************* \n");
    DumbDataType * lore = new DumbDataType();
    delete lore;

    getchar();
}

Output when I run this

STARTING MEMORY MANAGEMENT TESTING 
******************* Creating DATA ******************* 
[New] 28 
[New] 8 
[Delete] 00D88C18 
[Delete] 00D88BC8 
******************* Creating LORE *******************
[New] 28 
[New] 8 
[Delete] 00D88C18 
[Delete] 00D88BC8 

operators new and delete

void * operator new(std::size_t size, MemoryManagement::Heap* heap)
{
    assert(heap != nullptr);
    assert(size > 0);
    return heap->Allocate(size);
}

void * operator new(std::size_t size)
{
    printf("[New] %i \n", size);
    return operator new (size, MemoryManagement::HeapFactory::GetDefaultHeap());
}

void operator delete (void * memoryLocation)
{
    if (memoryLocation != NULL)
    {
        printf("[Delete] %p \n", memoryLocation);
        MemoryManagement::Heap::Deallocate(memoryLocation);
    }
}

The 'GetDefaultHeap' method just gets the first element in a statically allocated array of heaps.

Allocate mallocs enough memory for the size and a header and returns the proper starting address after offsetting for the header. Deallocate subtracts the header offset from the memory address it gets and frees that memory (I can post these methods if they help, it just seemed like too much code)

Upvotes: 3

Views: 512

Answers (2)

Vidrohi
Vidrohi

Reputation: 112

As @YSC pointed out, here is why there are two calls to new. The first new allocates the std::string object and returns a pointer to it, but that std::string object also has a pointer inside it and when it gets constructed it also calls new.

class DumberDataType
{
public:
    DumberDataType()
    {
        i = new int;
    }

private:
    int * i;

};

class DumbDataType
{
    DumberDataType ddt;
};

int main()
{
    printf("STARTING MEMORY MANAGEMENT TESTING \n");

    printf("******************* Creating DATA ******************* \n");
    DumbDataType* data = new DumbDataType();

    getchar();
}

The output of this code is

STARTING MEMORY MANAGEMENT TESTING
******************* Creating DATA *******************
[New] 4
[New] 4

Upvotes: 1

YSC
YSC

Reputation: 40070

new std::string()

This needs two allocations: one for the std::string object, another for its underlying memory buffer.

If you wrote

std::string s;

you'll see it calls new once.

Upvotes: 6

Related Questions