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