I'm having difficulties specifying the initialization order for some memory management tools.
We start with an overload of the Global new operator:
The macros pull / release memory from a pre-determined pool that is managed by the tool.
According to developer.Apple.com, the global operator new will be used for all code even the system / platform code that gets compiled into the project. This is fine.
The problem is in the initialization order. The macros ALLOC() and FREE() call functions that expect the memory tool to have been initialized prior to use. But the system code is calling global operator new prior to the initialization of the memory subsystem.
For most GCC related platforms this can be fixed with the following code:
Where 100 specifies the priority, the lower the number the sooner it gets initialized. 100 seems to be the base priority for user generated code. 99- throws up a compiler warning that "Requested init_priority is reserved for internal use."
If we set the priority to 0, we get an Error, "Requested inti_priority is out of range.".
We can ignore the warning for now, and set the Priority to 1. The highest priority allowed, which should make it the first thing initialized.
Unfortunately, Thats not what happens.
A different unit gets initialized first, which uses STL, STL in turn uses operator new, which calls into my code, and crashes becuase the MemorySubsystem has not been initialized.
Here is the call stack:
#6 is the initialization code for the unit.
#1 calls my global operator new overload.
#0 calls into my memory subsystem, where it crashes.
Any help with specifying the proper initialization order would be greatly appreciated.
Thanks,
Dan -
We start with an overload of the Global new operator:
Code:
// standard new
void * C_DECL operator new (size_t size) {
return ALLOC(size);
}
// standard delete
void C_DECL operator delete (void * ptr) {
FREE(ptr);
}
// array new
void * C_DECL operator new [] (size_t size) {
return ALLOC(size);
}
// array delete
void C_DECL operator delete [] (void * ptr) {
FREE(ptr);
}
The macros pull / release memory from a pre-determined pool that is managed by the tool.
According to developer.Apple.com, the global operator new will be used for all code even the system / platform code that gets compiled into the project. This is fine.
The problem is in the initialization order. The macros ALLOC() and FREE() call functions that expect the memory tool to have been initialized prior to use. But the system code is calling global operator new prior to the initialization of the memory subsystem.
For most GCC related platforms this can be fixed with the following code:
Code:
MemorySubsystem g_memoryPool __attribute__((init_priority(100))) ();
Where 100 specifies the priority, the lower the number the sooner it gets initialized. 100 seems to be the base priority for user generated code. 99- throws up a compiler warning that "Requested init_priority is reserved for internal use."
If we set the priority to 0, we get an Error, "Requested inti_priority is out of range.".
We can ignore the warning for now, and set the Priority to 1. The highest priority allowed, which should make it the first thing initialized.
Code:
MemorySubsystem g_memoryPool __attribute__((init_priority(1))) ();
Unfortunately, Thats not what happens.
A different unit gets initialized first, which uses STL, STL in turn uses operator new, which calls into my code, and crashes becuase the MemorySubsystem has not been initialized.
Here is the call stack:
#0 0x00002a38 in BitMemoryAbstraction::bit_alloc at Memory.cpp:60
#1 0x00007749 in operator new at Memory.cpp:124
#2 0x0358d671 in std::vector<__gnu_cxx::_Hashtable_node<std:air<std::string const, unsigned char> >*, std::allocator<__gnu_cxx::_Hashtable_node<std:
air<std::string const, unsigned char> >*> >::_M_allocate_and_copy<__gnu_cxx::_Hashtable_node<std:
air<std::string const, unsigned char> >**>
#3 0x0358d6ea in std::vector<__gnu_cxx::_Hashtable_node<std:air<std::string const, unsigned char> >*, std::allocator<__gnu_cxx::_Hashtable_node<std:
air<std::string const, unsigned char> >*> >::reserve
#4 0x0358db4e in __gnu_cxx::hashtable<std:air<std::string const, unsigned char>, std::string, __gnu_cxx::hash<std::string>, std::_Select1st<std:
air<std::string const, unsigned char> >, std::equal_to<std::string>, std::allocator<unsigned char> >::_M_initialize_buckets
#5 0x0358dbc2 in __gnu_cxx::hashtable<std:air<std::string const, unsigned char>, std::string, __gnu_cxx::hash<std::string>, std::_Select1st<std:
air<std::string const, unsigned char> >, std::equal_to<std::string>, std::allocator<unsigned char> >::hashtable
#6 0x0358e141 in __static_initialization_and_destruction_0
#7 0x8fe0ed6d in __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE
#8 0x8fe0d31e in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
#9 0x8fe0d2c2 in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
#10 0x8fe0d2c2 in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
#11 0x8fe0d2c2 in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
#12 0x8fe0d3d1 in __dyld__ZN11ImageLoader15runInitializersERKNS_11LinkContextE
#13 0x8fe024a9 in __dyld__ZN4dyld24initializeMainExecutableEv
#14 0x8fe07950 in __dyld__ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_
#15 0x8fe018b1 in __dyld__ZN13dyldbootstrap5startEPK12macho_headeriPPKcl
#16 0x8fe01057 in __dyld__dyld_start
#6 is the initialization code for the unit.
#1 calls my global operator new overload.
#0 calls into my memory subsystem, where it crashes.
Any help with specifying the proper initialization order would be greatly appreciated.
Thanks,
Dan -