1 // 2 // recalloc.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Implementation of _recalloc() 7 // 8 #include <corecrt_internal.h> 9 #include <malloc.h> 10 #include <string.h> 11 12 13 14 // This function provides the logic for the _recalloc() function. It is called 15 // only in the Release CRT (in the Debug CRT, the debug heap has its own 16 // implementation of _recalloc()). 17 // 18 // This function must be marked noinline, otherwise recalloc and 19 // _recalloc_base will have identical COMDATs, and the linker will fold 20 // them when calling one from the CRT. This is necessary because recalloc 21 // needs to support users patching in custom implementations. 22 extern "C" __declspec(noinline) void* __cdecl _recalloc_base( 23 void* const block, 24 size_t const count, 25 size_t const size 26 ) 27 { 28 // Ensure that (count * size) does not overflow 29 _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); 30 31 size_t const old_block_size = block != nullptr ? _msize_base(block) : 0; 32 size_t const new_block_size = count * size; 33 34 void* const new_block = _realloc_base(block, new_block_size); 35 36 // If the reallocation succeeded and the new block is larger, zero-fill the 37 // new bytes: 38 if (new_block != nullptr && old_block_size < new_block_size) 39 { 40 memset(static_cast<char*>(new_block) + old_block_size, 0, new_block_size - old_block_size); 41 } 42 43 return new_block; 44 } 45 46 // Reallocates a block of memory in the heap. 47 // 48 // This function reallocates the block pointed to by 'block' such that it is 49 // 'count * size' bytes in size. The new size may be either greater or less 50 // than the original size of the block. If the new size is greater than the 51 // original size, the new bytes are zero-filled. This function shares its 52 // implementation with the realloc() function; consult the comments of that 53 // function for more information about the implementation. 54 // 55 // This function supports patching and therefore must be marked noinline. 56 // Both _recalloc_dbg and _recalloc_base must also be marked noinline 57 // to prevent identical COMDAT folding from substituting calls to _recalloc 58 // with either other function or vice versa. 59 extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc( 60 void* const block, 61 size_t const count, 62 size_t const size 63 ) 64 { 65 #ifdef _DEBUG 66 return _recalloc_dbg(block, count, size, _NORMAL_BLOCK, nullptr, 0); 67 #else 68 return _recalloc_base(block, count, size); 69 #endif 70 } 71