xref: /reactos/sdk/lib/ucrt/heap/realloc_base.cpp (revision b09b5584)
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