Overridding new in C++, complications with local store

Started by
2 comments, last by TheUnbeliever 15 years, 10 months ago
I am looking into writing C++ memory management using plain new and delete in C++. I am using this classic article as reference. Here is the code snippet defining how new is overridden. The various parts of this snippet are not necessarily in the same .cpp file.


class Heap
{
protected:
  virtual ~Heap();
public:
  virtual void* allocate(size_t) = 0;
  static Heap& whatHeap(void*);
};

extern Heap* __global_heap;

inline void* operator new(size_t sz)
{
  return ::__global_heap->allocate(sz);
}

extern class HeapAny __THE_global_heap;
Heap* __global_heap = &__THE_global_heap;


Omitted from the snippet is the definition of the class HeapAny. This derives from Heap and the details of what it does aren't important to my query. Please also ignore the whatHeap() function in the Heap class. My query revolves around the instantiation of __THE_global_heap and assignment of it to __global_heap as in the last two lines of the program. As these are globally defined, they are created before main() is called and this invokes the overloaded new(). As the overloaded new() accesses __global_heap, yet __global_heap, or at least what it is pointing to hasn't been set up yet and is in fact the reason why the new() is being called, I can't see how this code works. I've tried this to see how it works out. Basically __global_heap appears to be NULL and the program crashes in the new statement, before main(). If I change the new to...

inline void* operator new(size_t sz)
{
  if( __global_heap == NULL ) return malloc( sz );
  return ::__global_heap->allocate(sz);
}


...then the program works as planned. However, I don't want every occurence of my overloaded new to be slowed down with 'if NULL' style checks. Does anyone have any familiarity with the article I am looking at, or perhaps some comment on how I might be able to control the problems I am looking at?
Advertisement
The easy solution is to wrap the global variable in a global function which declares the variable internally, as a static and returns it. Then you will always have your heap having been constructed prior to usage. You're getting hit by the order of instantiation being undefined for global variables.

That being said, any usage of overriding the global new is a little suspicious. You may want to ask yourself if you really need to do that. Making your own special purpose allocators for certain classes or types of objects may make sense, though.
Quote:
I don't want every occurence of my overloaded new to be slowed down with 'if NULL' style checks.

Well a comparison like your is very very fast and considering the context will not slow down your program if you don't make thousand memory allocations per second.

The singleton solution explained by Rydinare will help you but will not be very quicker than the NULL check. I can say you to not override the new operator but if you want a custom allocator you can build an allocation strategy like those used in the standard library.

The last thing: identifiers that start with _ or __ must not be used cause are reserved for compiler writers. If you want to protect the global allocator name from shadowing or name clash you can use a namespace ad hoc or a well chosen prefix.
--"Low level programming is good for the programmer's soul" -- John Carmack
Quote:Original post by zaerl
The last thing: identifiers that start with _ or __ must not be used cause are reserved for compiler writers.


Or rather: Identifiers that start with _ followed by an uppercase letter are reserved for any use. Identifiers containing __ anywhere at all are reserved for any use. Identifiers that start with _ followed by anything at all are reserved identifiers in the global namespace.
[TheUnbeliever]

This topic is closed to new replies.

Advertisement