Reputation: 6958
In order to track our memory usage and display some runtime statistics to the user (in a performant way) I'm overriding global new/delete (with a #define in a header - adding that header on top of every source file where we need to allocate/deallocate memory is going to ensure we can track all allocations going on).
I have two questions at this point since it's a multi-platform C++ codebase:
malloc
next to new
. I think I also need to override global malloc/free/calloc/realloc, is that correct?std::vector
). If I include my re-#defining header at the top of every source file, do I still need to pass a custom allocator like std::vector<int, my_allocator<int>>
? Or are the globally re-defined new/delete
enough? I think I still need the custom allocator but I'm not sure.Upvotes: 2
Views: 1289
Reputation: 2278
new
is implemented are property of a particular implementation of standard library - not even a compiler or operation system. All of them, at least, the three big ones, (CLang, GCC and MSVC) are using malloc()
within operator new
, because it just makes a life of library developer so much easier. So, yes, you will need to override the malloc/free/calloc/realloc
.std::vector
uses std::allocator
by default, and std::allocator
is required to use global operator new
, that is, ::operator new(size_t)
to obtain the memory. However, it isn't required to call it exactly once per call to allocator::allocate
.
If you replace global operator new
, then vector will use it, although not necessarily in a way that really allows your implementation to manage memory "efficiently". Any special tricks you want to use could, in principle, be made completely irrelevant by std::allocator
grabbing memory in 10MB chunks and sub-allocating.
You are fighting against a legacy old codebase. Any pure text replacement, like #define
preprocessor directives are really discouraged (luckily, some day C++ will get rid out of preprocessor), but, in your concrete case, it could be a viable approach.
Upvotes: 5
Reputation: 15275
If containers, like for example std::vector
use the default allocater std::allocater
as described here, then the std::allocater
will call the global new function in its allocate
function, as described here.
Allocates n * sizeof(T) bytes of uninitialized storage by calling ::operator new(std::size_t) or ::operator new(std::size_t, std::align_val_t) (since C++17)
So, it will call the global new
and if you override it then your implementation will be called. Please see the below example:
#include <iostream>
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;
void * operator new(size_t size)
{
cout << "New operator overloading " << endl;
void * p = malloc(size);
return p;
}
int main()
{
std::vector<int> v{};
v.resize(50);
v.resize(1500);
}
Upvotes: 1