@@ -42,13 +42,23 @@ find_original_function(const char * name)
4242 return original_function;
4343}
4444
45+ // An amount of memory that is greater than what is needed for static initialization
46+ // for any test we run. It was found experimentally on Ubuntu Linux 16.04 x86_64.
47+ static constexpr size_t STATIC_ALLOCATOR_SIZE = 0x800000 ;
4548using osrf_testing_tools_cpp::memory_tools::impl::StaticAllocator;
46- // the size was found experimentally on Ubuntu Linux 16.04 x86_64
47- using StaticAllocatorT = StaticAllocator<8388608 >;
48- // used to fullfil calloc call from dlerror.c during initialization of original functions
49- // constructor is called on first use with a placement-new and the static storage
49+ using StaticAllocatorT = StaticAllocator<STATIC_ALLOCATOR_SIZE>;
5050static uint8_t g_static_allocator_storage[sizeof (StaticAllocatorT)];
51- static StaticAllocatorT * g_static_allocator = nullptr ;
51+
52+ // Contains global allocator to make 100% sure to avoid Static Initialization Order Fiasco.
53+ // "Construct on first use" idiom
54+ static StaticAllocatorT *
55+ get_static_allocator ()
56+ {
57+ // placement-new the static allocator in preallocated storage
58+ // which is used while finding the original memory functions
59+ static StaticAllocatorT * alloc = new (g_static_allocator_storage) StaticAllocatorT;
60+ return alloc;
61+ }
5262
5363// storage for original malloc/realloc/calloc/free
5464using MallocSignature = void * (*)(size_t );
@@ -78,12 +88,7 @@ void *
7888malloc (size_t size) noexcept
7989{
8090 if (!get_static_initialization_complete ()) {
81- if (nullptr == g_static_allocator) {
82- // placement-new the static allocator
83- // which is used while finding the original memory functions
84- g_static_allocator = new (g_static_allocator_storage) StaticAllocatorT;
85- }
86- return g_static_allocator->allocate (size);
91+ return get_static_allocator ()->allocate (size);
8792 }
8893 return unix_replacement_malloc (size, g_original_malloc);
8994}
@@ -92,12 +97,7 @@ void *
9297realloc (void * pointer, size_t size) noexcept
9398{
9499 if (!get_static_initialization_complete ()) {
95- if (nullptr == g_static_allocator) {
96- // placement-new the static allocator
97- // which is used while finding the original memory functions
98- g_static_allocator = new (g_static_allocator_storage) StaticAllocatorT;
99- }
100- return g_static_allocator->reallocate (pointer, size);
100+ return get_static_allocator ()->reallocate (pointer, size);
101101 }
102102 return unix_replacement_realloc (pointer, size, g_original_realloc);
103103}
@@ -106,20 +106,15 @@ void *
106106calloc (size_t count, size_t size) noexcept
107107{
108108 if (!get_static_initialization_complete ()) {
109- if (nullptr == g_static_allocator) {
110- // placement-new the static allocator
111- // which is used while finding the original memory functions
112- g_static_allocator = new (g_static_allocator_storage) StaticAllocatorT;
113- }
114- return g_static_allocator->zero_allocate (count, size);
109+ return get_static_allocator ()->zero_allocate (count, size);
115110 }
116111 return unix_replacement_calloc (count, size, g_original_calloc);
117112}
118113
119114void
120115free (void * pointer) noexcept
121116{
122- if (nullptr == pointer || g_static_allocator ->deallocate (pointer)) {
117+ if (nullptr == pointer || get_static_allocator () ->deallocate (pointer)) {
123118 // free of nullptr or,
124119 // memory was originally allocated by static allocator, no need to pass to "real" free
125120 return ;
0 commit comments