@@ -42,13 +42,23 @@ find_original_function(const char * name)
42
42
return original_function;
43
43
}
44
44
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 ;
45
48
using 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>;
50
50
static 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
+ }
52
62
53
63
// storage for original malloc/realloc/calloc/free
54
64
using MallocSignature = void * (*)(size_t );
@@ -78,12 +88,7 @@ void *
78
88
malloc (size_t size) noexcept
79
89
{
80
90
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);
87
92
}
88
93
return unix_replacement_malloc (size, g_original_malloc);
89
94
}
@@ -92,12 +97,7 @@ void *
92
97
realloc (void * pointer, size_t size) noexcept
93
98
{
94
99
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);
101
101
}
102
102
return unix_replacement_realloc (pointer, size, g_original_realloc);
103
103
}
@@ -106,20 +106,15 @@ void *
106
106
calloc (size_t count, size_t size) noexcept
107
107
{
108
108
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);
115
110
}
116
111
return unix_replacement_calloc (count, size, g_original_calloc);
117
112
}
118
113
119
114
void
120
115
free (void * pointer) noexcept
121
116
{
122
- if (nullptr == pointer || g_static_allocator ->deallocate (pointer)) {
117
+ if (nullptr == pointer || get_static_allocator () ->deallocate (pointer)) {
123
118
// free of nullptr or,
124
119
// memory was originally allocated by static allocator, no need to pass to "real" free
125
120
return ;
0 commit comments