Reputation: 112
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
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
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