1 // 2 // realloc_base.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Implementation of _realloc_base(). This is defined in a different source 7 // file from the realloc() function to allow realloc() to be replaced by the 8 // user. 9 // 10 #include <corecrt_internal.h> 11 #include <malloc.h> 12 #include <new.h> 13 14 15 16 // This function implements the logic of realloc(). It is called directly by 17 // the realloc() and _recalloc() functions in the Release CRT and is called by 18 // the debug heap in the Debug CRT. 19 // 20 // This function must be marked noinline, otherwise realloc and 21 // _realloc_base will have identical COMDATs, and the linker will fold 22 // them when calling one from the CRT. This is necessary because realloc 23 // needs to support users patching in custom implementations. 24 extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _realloc_base( 25 void* const block, 26 size_t const size 27 ) 28 { 29 // If the block is a nullptr, just call malloc: 30 if (block == nullptr) 31 return _malloc_base(size); 32 33 // If the new size is 0, just call free and return nullptr: 34 if (size == 0) 35 { 36 _free_base(block); 37 return nullptr; 38 } 39 40 // Ensure that the requested size is not too large: 41 _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); 42 43 for (;;) 44 { 45 void* const new_block = HeapReAlloc(__acrt_heap, 0, block, size); 46 if (new_block) 47 return new_block; 48 49 // Otherwise, see if we need to call the new handler, and if so call it. 50 // If the new handler fails, just return nullptr: 51 if (_query_new_mode() == 0 || !_callnewh(size)) 52 { 53 errno = ENOMEM; 54 return nullptr; 55 } 56 57 // The new handler was successful; try to allocate again... 58 } 59 } 60