1 // 2 // calloc_base.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Implementation of _calloc_base(). This is defined in a different source file 7 // from the calloc() function to allow calloc() to be replaced by the user. 8 // 9 #include <corecrt_internal.h> 10 #include <malloc.h> 11 #include <new.h> 12 13 // This function implements the logic of calloc(). 14 // 15 // This function must be marked noinline, otherwise calloc and 16 // _calloc_base will have identical COMDATs, and the linker will fold 17 // them when calling one from the CRT. This is necessary because calloc 18 // needs to support users patching in custom implementations. 19 extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _calloc_base( 20 size_t const count, 21 size_t const size 22 ) 23 { 24 // Ensure that (count * size) does not overflow 25 _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); 26 27 // Ensure that we allocate a nonzero block size: 28 size_t const requested_block_size = count * size; 29 size_t const actual_block_size = requested_block_size == 0 30 ? 1 31 : requested_block_size; 32 33 for (;;) 34 { 35 void* const block = HeapAlloc(__acrt_heap, HEAP_ZERO_MEMORY, actual_block_size); 36 37 // If allocation succeeded, return the pointer to the new block: 38 if (block) 39 { 40 return block; 41 } 42 43 // Otherwise, see if we need to call the new handler, and if so call it. 44 // If the new handler fails, just return nullptr: 45 if (_query_new_mode() == 0 || !_callnewh(actual_block_size)) 46 { 47 errno = ENOMEM; 48 return nullptr; 49 } 50 51 // The new handler was successful; try to allocate aagain... 52 } 53 } 54