ReactOS 0.4.16-dev-853-g88d9285
debug_heap.cpp File Reference
#include <corecrt_internal.h>
#include <malloc.h>
#include <minmax.h>
#include <new.h>
#include <stdio.h>
#include <stdlib.h>
Include dependency graph for debug_heap.cpp:

Go to the source code of this file.

Classes

struct  _CrtMemBlockHeader
 
struct  _AlignMemBlockHdr
 

Macros

#define _DEBUG
 
#define _ALLOCATION_FILE_LINENUM   "\nMemory allocated at %hs(%d).\n"
 
#define IS_2_POW_N(X)   ((X) != 0 && ((X) & ((X) - 1)) == 0)
 

Functions

int__p__crtDbgFlag ()
 
long__p__crtBreakAlloc ()
 
static unsigned char *__cdecl block_from_header (_CrtMemBlockHeader *const header) throw ()
 
static _CrtMemBlockHeader *__cdecl header_from_block (void const *const block) throw ()
 
static bool __cdecl is_block_type_valid (int const block_use) throw ()
 
static bool __cdecl check_bytes (unsigned char const *const first, unsigned char const value, size_t const size) throw ()
 
static bool __cdecl is_bad_read_pointer (void const *const p, size_t const size) throw ()
 
static bool __cdecl is_block_an_aligned_allocation (void const *const block) throw ()
 
static void __cdecl validate_heap_if_required_nolock () throw ()
 
static void *__cdecl heap_alloc_dbg_internal (size_t const size, int const block_use, char const *const file_name, int const line_number) throw ()
 
static void *__cdecl heap_alloc_dbg (size_t const size, int const block_use, char const *const file_name, int const line_number) throw ()
 
 __declspec (noinline) void *__cdecl _malloc_dbg(size_t const size
 
 if (block) memset(block
 
static void *__cdecl realloc_dbg_nolock (void *const block, size_t *const new_size, int const block_use, char const *const file_name, int const line_number, bool const reallocation_is_allowed) throw ()
 
 __acrt_lock (__acrt_heap_lock)
 
 if (!new_block) return nullptr
 
 if (old_allocation_size< new_allocation_size)
 
 if (requested_size > static_cast< size_t >(_HEAP_MAXREQ - no_mans_land_size - sizeof(_CrtMemBlockHeader)))
 
static void __cdecl free_dbg_nolock (void *const block, int const block_use) throw ()
 
 free_dbg_nolock (block, actual_use)
 
 _VALIDATE_RETURN (block !=nullptr, EINVAL, static_cast< size_t >(-1))
 
 _ASSERTE (_CrtIsValidHeapPointer(block))
 
 _ASSERTE (is_block_type_valid(header->_block_use))
 
long __cdecl _CrtSetBreakAlloc (long const new_break_alloc)
 
void __cdecl _CrtSetDbgBlockType (void *const block, int const block_use)
 
_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ()
 
_CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook (_CRT_ALLOC_HOOK const new_hook)
 
static bool __cdecl check_block (_CrtMemBlockHeader *const header) throw ()
 
int __cdecl _CrtCheckMemory ()
 
int __cdecl _CrtSetDbgFlag (int const new_bits)
 
void __cdecl _CrtDoForAllClientObjects (_CrtDoForAllClientObjectsCallback const callback, void *const context)
 
int __cdecl _CrtIsValidPointer (void const *const p, unsigned int const size_in_bytes, int const read_write)
 
int __cdecl _CrtIsValidHeapPointer (void const *const block)
 
int __cdecl _CrtIsMemoryBlock (void const *const block, unsigned const size, long *const request_number, char **const file_name, int *const line_number)
 
int _CrtReportBlockType (void const *const block)
 
_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ()
 
_CRT_DUMP_CLIENT __cdecl _CrtSetDumpClient (_CRT_DUMP_CLIENT const new_client)
 
void __cdecl _CrtMemCheckpoint (_CrtMemState *const state)
 
int __cdecl _CrtMemDifference (_CrtMemState *const state, _CrtMemState const *const old_state, _CrtMemState const *const new_state)
 
static void __cdecl print_block_data (_locale_t const locale, _CrtMemBlockHeader *const header) throw ()
 
static void __cdecl dump_all_object_since_nolock (_CrtMemState const *const state) throw ()
 
void __cdecl _CrtMemDumpAllObjectsSince (_CrtMemState const *const state)
 
int __cdecl _CrtDumpMemoryLeaks ()
 
void __cdecl _CrtMemDumpStatistics (_CrtMemState const *const state)
 
void *__cdecl _aligned_malloc_dbg (size_t const size, size_t const alignment, char const *const file_name, int const line_number)
 
void *__cdecl _aligned_offset_malloc_dbg (size_t const size, size_t alignment, size_t const offset, char const *const file_name, int const line_number)
 
void *__cdecl _aligned_realloc_dbg (void *const block, size_t const size, size_t const alignment, char const *const file_name, int const line_number)
 
void *__cdecl _aligned_recalloc_dbg (void *const block, size_t const count, size_t const size, size_t const alignment, char const *const file_name, int const line_number)
 
void *__cdecl _aligned_offset_realloc_dbg (void *block, size_t size, size_t alignment, size_t offset, const char *file_name, int line_number)
 
size_t __cdecl _aligned_msize_dbg (void *const block, size_t alignment, size_t const offset)
 
void *__cdecl _aligned_offset_recalloc_dbg (void *const block, size_t const count, size_t const element_size, size_t const alignment, size_t const offset, char const *const file_name, int const line_number)
 
void __cdecl _aligned_free_dbg (void *const block)
 

Variables

static char const *const block_use_names [_MAX_BLOCKS]
 
static unsigned char const no_mans_land_fill {0xFD}
 
static unsigned char const align_land_fill {0xED}
 
static unsigned char const dead_land_fill {0xDD}
 
static unsigned char const clean_land_fill {0xCD}
 
static size_t const no_mans_land_size = 4
 
static size_t const align_gap_size = sizeof(void *)
 
static long const request_number_for_ignore_blocks {0}
 
static int const line_number_for_ignore_blocks {static_cast<int>(0xFEDCBABC)}
 
static _CrtMemBlockHeader__acrt_first_block {nullptr}
 
static _CrtMemBlockHeader__acrt_last_block {nullptr}
 
static size_t __acrt_total_allocations {0}
 
static size_t __acrt_current_allocations {0}
 
static size_t __acrt_max_allocations {0}
 
static unsigned __acrt_check_frequency {0}
 
static unsigned __acrt_check_counter {0}
 
static long __acrt_current_request_number {1}
 
int _crtDbgFlag {_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_DEFAULT_DF}
 
long _crtBreakAlloc {-1}
 
_CRT_DUMP_CLIENT _pfnDumpClient {nullptr}
 
static bool heap_validation_pending {false}
 
int const block_use
 
int const char const *const file_name
 
int const char const *const int const line_number
 
size_t const element_size
 
size_t const allocation_size {element_size * count}
 
void *const block {heap_alloc_dbg(allocation_size, block_use, file_name, line_number)}
 
size_t const requested_size
 
 __try
 
 new_block = realloc_dbg_nolock(block, &new_size, block_use, file_name, line_number, true)
 
 __finally
 
size_t const count
 
size_t const old_allocation_size {block ? _msize_dbg(block, block_use) : 0}
 
size_t const new_allocation_size {element_size * count }
 
size_t size {0}
 
_CrtMemBlockHeader *const header {header_from_block(block)}
 

Macro Definition Documentation

◆ _ALLOCATION_FILE_LINENUM

#define _ALLOCATION_FILE_LINENUM   "\nMemory allocated at %hs(%d).\n"

Definition at line 27 of file debug_heap.cpp.

◆ _DEBUG

#define _DEBUG

Definition at line 10 of file debug_heap.cpp.

◆ IS_2_POW_N

#define IS_2_POW_N (   X)    ((X) != 0 && ((X) & ((X) - 1)) == 0)

Definition at line 1783 of file debug_heap.cpp.

Function Documentation

◆ __acrt_lock()

◆ __declspec()

__declspec ( noinline  ) const

◆ __p__crtBreakAlloc()

long * __p__crtBreakAlloc ( )

Definition at line 155 of file debug_heap.cpp.

156{
157 return &_crtBreakAlloc;
158}
long _crtBreakAlloc
Definition: debug_heap.cpp:146

◆ __p__crtDbgFlag()

int * __p__crtDbgFlag ( )

Definition at line 150 of file debug_heap.cpp.

151{
152 return &_crtDbgFlag;
153}
int _crtDbgFlag
Definition: debug_heap.cpp:145

◆ _aligned_free_dbg()

void __cdecl _aligned_free_dbg ( void *const  block)

Definition at line 1972 of file debug_heap.cpp.

1973{
1974 if (!block)
1975 return;
1976
1977 _AlignMemBlockHdr* const header{reinterpret_cast<_AlignMemBlockHdr*>(
1978 reinterpret_cast<uintptr_t>(block) & ~(sizeof(uintptr_t) - 1)
1979 ) -1};
1980
1981 if (check_bytes(static_cast<unsigned char*>(block) - no_mans_land_size, no_mans_land_fill, no_mans_land_size))
1982 {
1983 // We don't know where (file, linenum) block was allocated
1984 _RPTN(_CRT_ERROR, "The block at 0x%p was not allocated by _aligned routines, use free()", block);
1985 return;
1986 }
1987
1989 {
1990 // We don't know where (file, linenum) block was allocated
1991 _RPTN(_CRT_ERROR, "Damage before 0x%p which was allocated by aligned routine\n", block);
1992 }
1993
1995}
#define _free_dbg(p, t)
Definition: crtdbg.h:209
#define _CRT_ERROR
Definition: crtdbg.h:21
#define _NORMAL_BLOCK
Definition: crtdbg.h:67
#define _RPTN(rptno, msg,...)
Definition: crtdbg.h:119
static bool __cdecl check_bytes(unsigned char const *const first, unsigned char const value, size_t const size)
Definition: debug_heap.cpp:187
static size_t const align_gap_size
Definition: debug_heap.cpp:66
static unsigned char const align_land_fill
Definition: debug_heap.cpp:60
static unsigned char const no_mans_land_fill
Definition: debug_heap.cpp:59
static size_t const no_mans_land_size
Definition: debug_heap.cpp:65
void *const block
Definition: debug_heap.cpp:523
unsigned int uintptr_t
Definition: intrin.h:47

◆ _aligned_malloc_dbg()

void *__cdecl _aligned_malloc_dbg ( size_t const  size,
size_t const  alignment,
char const *const  file_name,
int const  line_number 
)

Definition at line 1787 of file debug_heap.cpp.

1793{
1795}
_Check_return_ _Ret_maybenull_ _In_ size_t alignment
Definition: align.cpp:48
#define _aligned_offset_malloc_dbg(s, a, o, f, l)
Definition: crtdbg.h:216
int const char const *const file_name
Definition: debug_heap.cpp:496
int const char const *const int const line_number
Definition: debug_heap.cpp:499
GLsizeiptr size
Definition: glext.h:5919

◆ _aligned_msize_dbg()

size_t __cdecl _aligned_msize_dbg ( void *const  block,
size_t  alignment,
size_t const  offset 
)

Definition at line 1917 of file debug_heap.cpp.

1922{
1923 size_t header_size = 0; // Size of the header block
1924 size_t footer_size = 0; // Size of the footer block
1925 size_t total_size = 0; // total size of the allocated block
1926 size_t user_size = 0; // size of the user block
1927 uintptr_t gap = 0; // keep the alignment of the data block
1928 // after the sizeof(void*) aligned pointer
1929 // to the beginning of the allocated block
1930
1931 // HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER
1932 // HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE
1933 _VALIDATE_RETURN (block != nullptr, EINVAL, static_cast<size_t>(-1));
1934
1935 _AlignMemBlockHdr* header_from_block = nullptr; // points to the beginning of the allocated block
1936 header_from_block = (_AlignMemBlockHdr*)((uintptr_t)block & ~(sizeof(uintptr_t) - 1)) - 1;
1937 total_size = _msize_dbg(header_from_block->_head, _NORMAL_BLOCK);
1938 header_size = (uintptr_t)block - (uintptr_t)header_from_block->_head;
1939 gap = (0 - offset) & (sizeof(uintptr_t) - 1);
1940 // The alignment cannot be smaller than the sizeof(uintptr_t)
1941 alignment = (alignment > sizeof(uintptr_t) ? alignment : sizeof(uintptr_t)) - 1;
1942 footer_size = gap + alignment + sizeof(_AlignMemBlockHdr) - header_size;
1943 user_size = total_size - header_size - footer_size;
1944 return user_size;
1945}
#define EINVAL
Definition: acclib.h:90
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
#define _msize_dbg(p, t)
Definition: crtdbg.h:210
static _CrtMemBlockHeader *__cdecl header_from_block(void const *const block)
Definition: debug_heap.cpp:172
GLintptr offset
Definition: glext.h:5920

◆ _aligned_offset_malloc_dbg()

void *__cdecl _aligned_offset_malloc_dbg ( size_t const  size,
size_t  alignment,
size_t const  offset,
char const *const  file_name,
int const  line_number 
)

Definition at line 1797 of file debug_heap.cpp.

1804{
1806 _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
1807
1808 alignment = (alignment > sizeof(uintptr_t) ? alignment : sizeof(uintptr_t)) - 1;
1809
1810 uintptr_t const t_ptr = (0 -offset) & (sizeof(uintptr_t) -1);
1811
1812 size_t const nonuser_size = t_ptr + alignment + sizeof(_AlignMemBlockHdr); // Cannot overflow
1813 size_t const block_size = size + nonuser_size;
1815
1817 if (ptr == reinterpret_cast<uintptr_t>(nullptr))
1818 return nullptr;
1819
1820 uintptr_t const r_ptr = ((ptr +nonuser_size +offset)&~alignment)-offset;
1821 _AlignMemBlockHdr* const header_from_block = reinterpret_cast<_AlignMemBlockHdr*>(r_ptr - t_ptr) - 1;
1823 header_from_block->_head = reinterpret_cast<void*>(ptr);
1824 return reinterpret_cast<void*>(r_ptr);
1825}
#define ENOMEM
Definition: acclib.h:84
#define _malloc_dbg(s, t, f, l)
Definition: crtdbg.h:204
#define IS_2_POW_N(X)
#define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr)
static DWORD block_size(DWORD block)
Definition: jsutils.c:66
static PVOID ptr
Definition: dispmode.c:27
#define memset(x, y, z)
Definition: compat.h:39
unsigned char _gap[no_mans_land_size]
Definition: debug_heap.cpp:94

◆ _aligned_offset_realloc_dbg()

void *__cdecl _aligned_offset_realloc_dbg ( void block,
size_t  size,
size_t  alignment,
size_t  offset,
const char file_name,
int  line_number 
)

Definition at line 1850 of file debug_heap.cpp.

1858{
1859 uintptr_t ptr, r_ptr, t_ptr, mov_sz;
1860 _AlignMemBlockHdr *header_from_block, *s_header_from_block;
1861 size_t nonuser_size, block_size;
1862
1863 if (block == nullptr)
1864 {
1866 }
1867 if (size == 0)
1868 {
1870 return nullptr;
1871 }
1872
1873 s_header_from_block = (_AlignMemBlockHdr *)((uintptr_t)block & ~(sizeof(uintptr_t) -1)) -1;
1874
1876 {
1877 // We don't know where (file, linenum) block was allocated
1878 _RPTN(_CRT_ERROR, "The block at 0x%p was not allocated by _aligned routines, use realloc()", block);
1879 errno = EINVAL;
1880 return nullptr;
1881 }
1882
1883 if(!check_bytes(s_header_from_block->_gap, align_land_fill, align_gap_size))
1884 {
1885 // We don't know where (file, linenum) block was allocated
1886 _RPTN(_CRT_ERROR, "Damage before 0x%p which was allocated by aligned routine\n", block);
1887 }
1888
1889 /* validation section */
1891 _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
1892
1893 mov_sz = _msize_dbg(s_header_from_block->_head, _NORMAL_BLOCK) - ((uintptr_t)block - (uintptr_t)s_header_from_block->_head);
1894
1895 alignment = (alignment > sizeof(uintptr_t) ? alignment : sizeof(uintptr_t)) -1;
1896
1897 t_ptr = (0 -offset) & (sizeof(uintptr_t) - 1);
1898
1899 nonuser_size = t_ptr + alignment + sizeof(_AlignMemBlockHdr); // Cannot overflow
1900 block_size = size + nonuser_size;
1902
1904 return nullptr;
1905
1906 r_ptr = ((ptr + nonuser_size + offset) & ~alignment) - offset;
1907 header_from_block = (_AlignMemBlockHdr*)(r_ptr - t_ptr) - 1;
1909 header_from_block->_head = reinterpret_cast<void*>(ptr);
1910
1911 memcpy(reinterpret_cast<void*>(r_ptr), block, mov_sz > size ? size : mov_sz);
1912 _free_dbg(s_header_from_block->_head, _NORMAL_BLOCK);
1913
1914 return (void *) r_ptr;
1915}
#define _aligned_free_dbg(p)
Definition: crtdbg.h:215
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define errno
Definition: errno.h:18
unsigned char _gap[align_gap_size]

◆ _aligned_offset_recalloc_dbg()

void *__cdecl _aligned_offset_recalloc_dbg ( void *const  block,
size_t const  count,
size_t const  element_size,
size_t const  alignment,
size_t const  offset,
char const *const  file_name,
int const  line_number 
)

Definition at line 1947 of file debug_heap.cpp.

1956{
1958
1960 size_t const new_allocation_size{element_size * count};
1961
1963 if (!new_block)
1964 return nullptr;
1965
1967 memset(static_cast<unsigned char*>(new_block) + old_allocation_size, 0, new_allocation_size - old_allocation_size);
1968
1969 return new_block;
1970}
#define _aligned_offset_realloc_dbg(p, s, a, o, f, l)
Definition: crtdbg.h:217
#define _HEAP_MAXREQ
Definition: malloc.h:24
size_t const old_allocation_size
Definition: debug_heap.cpp:790
size_t const new_allocation_size
Definition: debug_heap.cpp:791
size_t const element_size
Definition: debug_heap.cpp:510
new_block
Definition: debug_heap.cpp:763
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define _aligned_msize_dbg(p, a, o)
Definition: crtdbg.h:260

◆ _aligned_realloc_dbg()

void *__cdecl _aligned_realloc_dbg ( void *const  block,
size_t const  size,
size_t const  alignment,
char const *const  file_name,
int const  line_number 
)

Definition at line 1827 of file debug_heap.cpp.

◆ _aligned_recalloc_dbg()

void *__cdecl _aligned_recalloc_dbg ( void *const  block,
size_t const  count,
size_t const  size,
size_t const  alignment,
char const *const  file_name,
int const  line_number 
)

Definition at line 1838 of file debug_heap.cpp.

1846{
1848}
#define _aligned_offset_recalloc_dbg(p, c, s, a, o, f, l)
Definition: crtdbg.h:218

◆ _ASSERTE() [1/2]

_ASSERTE ( _CrtIsValidHeapPointer(block )

◆ _ASSERTE() [2/2]

_ASSERTE ( is_block_type_valid(header->_block_use)  )

◆ _CrtCheckMemory()

int __cdecl _CrtCheckMemory ( )

Definition at line 1256 of file debug_heap.cpp.

1257{
1258 if ((_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF) == 0)
1259 {
1260 return TRUE;
1261 }
1262
1263 bool all_okay{true};
1264
1266 __try
1267 {
1268 // First walk our allocated heap blocks and verify consistency of our
1269 // internal data structures. We do this first because we can give
1270 // better diagnostics to client code than the underlying Windows heap
1271 // can (we have source file names and line numbers and other metadata).
1272 // We use Floyd's cycle finding algorithm to detect cycles in the block
1273 // list.
1276 while (trail_it != nullptr)
1277 {
1278 all_okay &= check_block(trail_it);
1279
1280 if (trail_it == lead_it)
1281 {
1283 "Cycle in block list detected while processing block located at 0x%p.\n",
1284 trail_it);
1285 all_okay = false;
1286 break;
1287 }
1288
1289 trail_it = trail_it->_block_header_next;
1290
1291 // Advance the lead iterator twice as fast as the trail iterator:
1292 if (lead_it != nullptr)
1293 {
1294 lead_it = lead_it->_block_header_next == nullptr
1295 ? nullptr
1296 : lead_it->_block_header_next->_block_header_next;
1297 }
1298 }
1299
1300 // Then check the underlying Windows heap:
1301 if (!HeapValidate(__acrt_heap, 0, nullptr))
1302 {
1303 _RPT0(_CRT_WARN, "Heap validation failed.\n");
1304 all_okay = false;
1305 __leave;
1306 }
1307 }
1308 __finally
1309 {
1311 }
1312 __endtry
1313
1314 return all_okay ? TRUE : FALSE;
1315}
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_heap_lock
#define _CRT_WARN
Definition: crtdbg.h:20
#define _RPT0(rptno, msg)
Definition: crtdbg.h:118
#define _CRTDBG_ALLOC_MEM_DF
Definition: crtdbg.h:48
static _CrtMemBlockHeader * __acrt_first_block
Definition: debug_heap.cpp:114
static bool __cdecl check_block(_CrtMemBlockHeader *const header)
__acrt_lock(__acrt_heap_lock)
__try
Definition: debug_heap.cpp:761
__finally
Definition: debug_heap.cpp:766
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
return nullptr
Definition: expand.cpp:78
HANDLE __acrt_heap
Definition: heap_handle.cpp:15
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
Definition: heapmem.c:156
#define __leave
Definition: pseh2_64.h:176
#define __endtry
Definition: pseh2_64.h:175
_CrtMemBlockHeader * _block_header_next
Definition: debug_heap.cpp:85

Referenced by validate_heap_if_required_nolock().

◆ _CrtDoForAllClientObjects()

void __cdecl _CrtDoForAllClientObjects ( _CrtDoForAllClientObjectsCallback const  callback,
void *const  context 
)

Definition at line 1364 of file debug_heap.cpp.

1368{
1370
1371 if ((_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF) == 0)
1372 return;
1373
1375 __try
1376 {
1377 for (_CrtMemBlockHeader* header{__acrt_first_block}; header != nullptr; header = header->_block_header_next)
1378 {
1379 if (_BLOCK_TYPE(header->_block_use) == _CLIENT_BLOCK)
1381 }
1382 }
1383 __finally
1384 {
1386 }
1387 __endtry
1388}
#define _VALIDATE_RETURN_VOID(expr, errorcode)
#define _CLIENT_BLOCK
Definition: crtdbg.h:70
#define _BLOCK_TYPE(block)
Definition: crtdbg.h:63
static unsigned char *__cdecl block_from_header(_CrtMemBlockHeader *const header)
Definition: debug_heap.cpp:167
static IPrintDialogCallback callback
Definition: printdlg.c:326
Definition: http.c:7252

◆ _CrtDumpMemoryLeaks()

int __cdecl _CrtDumpMemoryLeaks ( )

Definition at line 1727 of file debug_heap.cpp.

1728{
1731
1732 if (state.lCounts[_CLIENT_BLOCK] != 0 ||
1733 state.lCounts[_NORMAL_BLOCK] != 0 ||
1734 (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF && state.lCounts[_CRT_BLOCK] != 0))
1735 {
1736 _RPT0(_CRT_WARN, "Detected memory leaks!\n");
1737
1739 return TRUE;
1740 }
1741
1742 return FALSE;
1743}
static int state
Definition: maze.c:121
#define _CrtMemDumpAllObjectsSince(s)
Definition: crtdbg.h:256
#define _CRTDBG_CHECK_CRT_DF
Definition: crtdbg.h:52
#define _CRT_BLOCK
Definition: crtdbg.h:68
#define _CrtMemCheckpoint(s)
Definition: crtdbg.h:254

◆ _CrtGetAllocHook()

_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ( )

Definition at line 1132 of file debug_heap.cpp.

1133{
1134 return _pfnAllocHook;
1135}
_CRT_ALLOC_HOOK _pfnAllocHook

◆ _CrtGetDumpClient()

_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ( )

Definition at line 1504 of file debug_heap.cpp.

1505{
1506 return _pfnDumpClient;
1507}
_CRT_DUMP_CLIENT _pfnDumpClient
Definition: debug_heap.cpp:147

◆ _CrtIsMemoryBlock()

int __cdecl _CrtIsMemoryBlock ( void const *const  block,
unsigned const  size,
long *const  request_number,
char **const  file_name,
int *const  line_number 
)

Definition at line 1429 of file debug_heap.cpp.

1436{
1437 if (request_number)
1438 *request_number = 0;
1439
1440 if (file_name)
1441 *file_name = nullptr;
1442
1443 if (line_number)
1444 *line_number = 0;
1445
1446 if (!block)
1447 return FALSE;
1448
1449 int result{FALSE};
1450
1452 __try
1453 {
1455 if (!is_block_type_valid(header->_block_use))
1456 __leave;
1457
1459 __leave;
1460
1461 if (header->_data_size != size)
1462 __leave;
1463
1464 if (header->_request_number > __acrt_current_request_number)
1465 __leave;
1466
1467 // The block is valid
1468 if (request_number)
1469 *request_number = header->_request_number;
1470
1471 if (file_name)
1472 *file_name = const_cast<char*>(header->_file_name);
1473
1474 if (line_number)
1475 *line_number = header->_line_number;
1476
1477 result = TRUE;
1478 }
1479 __finally
1480 {
1482 }
1483 __endtry
1484
1485 return result;
1486}
#define _CrtIsValidPointer(p, n, r)
Definition: crtdbg.h:248
static long __acrt_current_request_number
Definition: debug_heap.cpp:132
static bool __cdecl is_block_type_valid(int const block_use)
Definition: debug_heap.cpp:177
GLuint64EXT * result
Definition: glext.h:11304

◆ _CrtIsValidHeapPointer()

int __cdecl _CrtIsValidHeapPointer ( void const *const  block)

Definition at line 1414 of file debug_heap.cpp.

1415{
1416 if (!block)
1417 return FALSE;
1418
1420}

◆ _CrtIsValidPointer()

int __cdecl _CrtIsValidPointer ( void const *const  p,
unsigned int const  size_in_bytes,
int const  read_write 
)

Definition at line 1394 of file debug_heap.cpp.

1399{
1400 UNREFERENCED_PARAMETER(size_in_bytes);
1402
1403 return p != nullptr;
1404}
GLfloat GLfloat p
Definition: glext.h:8902
static const struct @1674 read_write[]
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325

◆ _CrtMemCheckpoint()

void __cdecl _CrtMemCheckpoint ( _CrtMemState *const  state)

Definition at line 1520 of file debug_heap.cpp.

1521{
1522 _VALIDATE_RETURN_VOID(state != nullptr, EINVAL);
1523
1525 __try
1526 {
1527 state->pBlockHeader = __acrt_first_block;
1528
1529 for (unsigned use{0}; use < _MAX_BLOCKS; ++use)
1530 {
1531 state->lCounts[use] = 0;
1532 state->lSizes [use] = 0;
1533 }
1534
1535 for (_CrtMemBlockHeader* header{__acrt_first_block}; header != nullptr; header = header->_block_header_next)
1536 {
1537 if (_BLOCK_TYPE(header->_block_use) >= 0 && _BLOCK_TYPE(header->_block_use) < _MAX_BLOCKS)
1538 {
1539 ++state->lCounts[_BLOCK_TYPE(header->_block_use)];
1540 state->lSizes[_BLOCK_TYPE(header->_block_use)] += header->_data_size;
1541 }
1542 else if (header->_file_name)
1543 {
1544 _RPTN(_CRT_WARN, "Bad memory block found at 0x%p.\n" _ALLOCATION_FILE_LINENUM,
1545 header,
1546 header->_file_name,
1547 header->_line_number);
1548 }
1549 else
1550 {
1551 _RPTN(_CRT_WARN, "Bad memory block found at 0x%p.\n", header);
1552 }
1553 }
1554
1555 state->lHighWaterCount = __acrt_max_allocations;
1556 state->lTotalCount = __acrt_total_allocations;
1557 }
1558 __finally
1559 {
1561 }
1562 __endtry
1563}
#define _MAX_BLOCKS
Definition: crtdbg.h:71
#define _ALLOCATION_FILE_LINENUM
Definition: debug_heap.cpp:27
static size_t __acrt_total_allocations
Definition: debug_heap.cpp:121
static size_t __acrt_max_allocations
Definition: debug_heap.cpp:123

◆ _CrtMemDifference()

int __cdecl _CrtMemDifference ( _CrtMemState *const  state,
_CrtMemState const *const  old_state,
_CrtMemState const *const  new_state 
)

Definition at line 1571 of file debug_heap.cpp.

1576{
1577 _VALIDATE_RETURN(state != nullptr, EINVAL, FALSE);
1578 _VALIDATE_RETURN(old_state != nullptr, EINVAL, FALSE);
1579 _VALIDATE_RETURN(new_state != nullptr, EINVAL, FALSE);
1580
1581 bool significant_difference_found{false};
1582 for (int use{0}; use < _MAX_BLOCKS; ++use)
1583 {
1584 state->lSizes[use] = new_state->lSizes[use] - old_state->lSizes[use];
1585 state->lCounts[use] = new_state->lCounts[use] - old_state->lCounts[use];
1586
1587 if (state->lSizes[use] == 0 && state->lCounts[use] == 0)
1588 continue;
1589
1590 if (use == _FREE_BLOCK)
1591 continue;
1592
1593 if (use == _CRT_BLOCK && (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF) == 0)
1594 continue;
1595
1596 significant_difference_found = true;
1597 }
1598
1599 state->lHighWaterCount = new_state->lHighWaterCount - old_state->lHighWaterCount;
1600 state->lTotalCount = new_state->lTotalCount - old_state->lTotalCount;
1601 state->pBlockHeader = nullptr;
1602
1603 return significant_difference_found ? 1 : 0;
1604}
#define _FREE_BLOCK
Definition: crtdbg.h:66

◆ _CrtMemDumpAllObjectsSince()

void __cdecl _CrtMemDumpAllObjectsSince ( _CrtMemState const *const  state)

Definition at line 1706 of file debug_heap.cpp.

1707{
1709 __try
1710 {
1712 }
1713 __finally
1714 {
1716 }
1717 __endtry
1718
1719 _RPT0(_CRT_WARN, "Object dump complete.\n");
1720}
static void __cdecl dump_all_object_since_nolock(_CrtMemState const *const state)

◆ _CrtMemDumpStatistics()

void __cdecl _CrtMemDumpStatistics ( _CrtMemState const *const  state)

Definition at line 1748 of file debug_heap.cpp.

1749{
1750 _VALIDATE_RETURN_VOID(state != nullptr, EINVAL);
1751
1752 for (unsigned use{0}; use < _MAX_BLOCKS; ++use)
1753 {
1754 _RPTN(_CRT_WARN, "%Id bytes in %Id %hs Blocks.\n",
1755 state->lSizes[use],
1756 state->lCounts[use],
1757 block_use_names[use]);
1758 }
1759
1760 _RPTN(_CRT_WARN, "Largest number used: %Id bytes.\n", state->lHighWaterCount);
1761 _RPTN(_CRT_WARN, "Total allocations: %Id bytes.\n", state->lTotalCount);
1762}
static char const *const block_use_names[_MAX_BLOCKS]
Definition: debug_heap.cpp:34

◆ _CrtReportBlockType()

int _CrtReportBlockType ( void const *const  block)

Definition at line 1492 of file debug_heap.cpp.

1493{
1495 return -1;
1496
1498}
#define _CrtIsValidHeapPointer(p)
Definition: crtdbg.h:249

◆ _CrtSetAllocHook()

_CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook ( _CRT_ALLOC_HOOK const  new_hook)

Definition at line 1137 of file debug_heap.cpp.

1138{
1139 _CRT_ALLOC_HOOK const old_hook{_pfnAllocHook};
1140 _pfnAllocHook = new_hook;
1141 return old_hook;
1142}
int(__cdecl * _CRT_ALLOC_HOOK)(int, void *, size_t, int, long, const unsigned char *, int)
Definition: crtdbg.h:46

◆ _CrtSetBreakAlloc()

long __cdecl _CrtSetBreakAlloc ( long const  new_break_alloc)

Definition at line 1094 of file debug_heap.cpp.

1095{
1096 long const old_break_alloc{_crtBreakAlloc};
1097 _crtBreakAlloc = new_break_alloc;
1098 return old_break_alloc;
1099}

◆ _CrtSetDbgBlockType()

void __cdecl _CrtSetDbgBlockType ( void *const  block,
int const  block_use 
)

Definition at line 1104 of file debug_heap.cpp.

1108{
1110 __try
1111 {
1113 __leave;
1114
1116
1117 _ASSERTE(is_block_type_valid(header->_block_use));
1118
1119 header->_block_use = block_use;
1120 }
1121 __finally
1122 {
1124 }
1125 __endtry
1126}
#define _ASSERTE(expr)
Definition: crtdbg.h:114
int const block_use
Definition: debug_heap.cpp:495

◆ _CrtSetDbgFlag()

int __cdecl _CrtSetDbgFlag ( int const  new_bits)

Definition at line 1322 of file debug_heap.cpp.

1323{
1324 int const valid_flags{
1330
1331 bool const new_bits_have_only_valid_flags = (new_bits & 0xffff & ~valid_flags) == 0;
1332 _VALIDATE_RETURN(new_bits == _CRTDBG_REPORT_FLAG || new_bits_have_only_valid_flags, EINVAL, _crtDbgFlag);
1333
1334 int old_bits{0};
1335
1337 __try
1338 {
1339 old_bits = _crtDbgFlag;
1340
1341 if (new_bits == _CRTDBG_REPORT_FLAG)
1342 __leave;
1343
1344 if (new_bits & _CRTDBG_CHECK_ALWAYS_DF)
1346 else
1347 __acrt_check_frequency = (new_bits >> 16) & 0x0ffff;
1348
1350 _crtDbgFlag = new_bits;
1351 }
1352 __finally
1353 {
1355 }
1356 __endtry
1357
1358 return old_bits;
1359}
#define _CRTDBG_CHECK_ALWAYS_DF
Definition: crtdbg.h:50
#define _CRTDBG_LEAK_CHECK_DF
Definition: crtdbg.h:53
#define _CRTDBG_REPORT_FLAG
Definition: crtdbg.h:61
#define _CRTDBG_DELAY_FREE_MEM_DF
Definition: crtdbg.h:49
static unsigned __acrt_check_frequency
Definition: debug_heap.cpp:127
static unsigned __acrt_check_counter
Definition: debug_heap.cpp:128

◆ _CrtSetDumpClient()

_CRT_DUMP_CLIENT __cdecl _CrtSetDumpClient ( _CRT_DUMP_CLIENT const  new_client)

Definition at line 1509 of file debug_heap.cpp.

1510{
1511 _CRT_DUMP_CLIENT const old_client{_pfnDumpClient};
1512 _pfnDumpClient = new_client;
1513 return old_client;
1514}
void(__cdecl * _CRT_DUMP_CLIENT)(void *, size_t)
Definition: crtdbg.h:73

◆ _VALIDATE_RETURN()

_VALIDATE_RETURN ( block = nullptr,
EINVAL  ,
static_cast< size_t -1 
)

◆ block_from_header()

static unsigned char *__cdecl block_from_header ( _CrtMemBlockHeader *const  header)
throw (
)
static

Definition at line 167 of file debug_heap.cpp.

168{
169 return reinterpret_cast<unsigned char*>(header + 1);
170}

Referenced by _CrtDoForAllClientObjects(), check_block(), dump_all_object_since_nolock(), free_dbg_nolock(), heap_alloc_dbg_internal(), print_block_data(), and realloc_dbg_nolock().

◆ check_block()

static bool __cdecl check_block ( _CrtMemBlockHeader *const  header)
throw (
)
static

Definition at line 1149 of file debug_heap.cpp.

1150{
1151 bool this_block_okay{true};
1152 char const* block_use{nullptr};
1153
1154 if (is_block_type_valid(header->_block_use))
1155 {
1157 }
1158 else
1159 {
1160 block_use = "DAMAGED";
1161 }
1162
1163 // Check the no-man's-land gaps:
1165 {
1166 if (header->_file_name)
1167 {
1168 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
1169 "CRT detected that the application wrote to memory before start of heap buffer.\n"
1171 block_use,
1172 header->_request_number,
1174 header->_file_name,
1175 header->_line_number);
1176 }
1177 else
1178 {
1179 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
1180 "CRT detected that the application wrote to memory before start of heap buffer.\n",
1181 block_use, header->_request_number, block_from_header(header));
1182 }
1183
1184 this_block_okay = false;
1185 }
1186
1188 {
1189 if (header->_file_name)
1190 {
1191 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
1192 "CRT detected that the application wrote to memory after end of heap buffer.\n"
1194 block_use,
1195 header->_request_number,
1197 header->_file_name,
1198 header->_line_number);
1199 }
1200 else
1201 {
1202 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
1203 "CRT detected that the application wrote to memory after end of heap buffer.\n",
1204 block_use, header->_request_number, block_from_header(header));
1205 }
1206
1207 this_block_okay = false;
1208 }
1209
1210 // Free blocks should remain undisturbed:
1211 if (header->_block_use == _FREE_BLOCK && !check_bytes(block_from_header(header), dead_land_fill, header->_data_size))
1212 {
1213 if (header->_file_name)
1214 {
1215 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: on top of Free block at 0x%p.\n"
1216 "CRT detected that the application wrote to a heap buffer that was freed.\n"
1219 header->_file_name,
1220 header->_line_number);
1221 }
1222 else
1223 {
1224 _RPTN(_CRT_WARN, "HEAP CORRUPTION DETECTED: on top of Free block at 0x%p.\n"
1225 "CRT detected that the application wrote to a heap buffer that was freed.\n",
1227 }
1228
1229 this_block_okay = false;
1230 }
1231
1232 if (!this_block_okay)
1233 {
1234 // Report statistics about the broken object:
1235 if (header->_file_name)
1236 {
1238 "%hs located at 0x%p is %Iu bytes long.\n"
1240 block_use,
1242 header->_data_size,
1243 header->_file_name,
1244 header->_line_number);
1245 }
1246 else
1247 {
1248 _RPTN(_CRT_WARN, "%hs located at 0x%p is %Iu bytes long.\n",
1249 block_use, block_from_header(header), header->_data_size);
1250 }
1251 }
1252
1253 return this_block_okay;
1254}
static unsigned char const dead_land_fill
Definition: debug_heap.cpp:61

Referenced by _CrtCheckMemory().

◆ check_bytes()

static bool __cdecl check_bytes ( unsigned char const *const  first,
unsigned char const  value,
size_t const  size 
)
throw (
)
static

Definition at line 187 of file debug_heap.cpp.

192{
193 unsigned char const* const last{first + size};
194 for (unsigned char const* it{first}; it != last; ++it)
195 {
196 if (*it != value)
197 return false;
198 }
199
200 return true;
201}
const GLint * first
Definition: glext.h:5794
static UINT UINT last
Definition: font.c:45
Definition: pdh_main.c:96

Referenced by _aligned_free_dbg(), _aligned_offset_realloc_dbg(), check_block(), free_dbg_nolock(), and is_block_an_aligned_allocation().

◆ dump_all_object_since_nolock()

static void __cdecl dump_all_object_since_nolock ( _CrtMemState const *const  state)
throw (
)
static

Definition at line 1635 of file debug_heap.cpp.

1636{
1637 _LocaleUpdate locale_update{nullptr};
1638 _locale_t locale{locale_update.GetLocaleT()};
1639
1640 _RPT0(_CRT_WARN, "Dumping objects ->\n");
1641
1642 _CrtMemBlockHeader* const stop_block{state ? state->pBlockHeader : nullptr};
1643
1644 for (_CrtMemBlockHeader* header{__acrt_first_block}; header != nullptr && header != stop_block; header = header->_block_header_next)
1645 {
1646 if (_BLOCK_TYPE(header->_block_use) == _IGNORE_BLOCK)
1647 continue;
1648
1649 if (_BLOCK_TYPE(header->_block_use) == _FREE_BLOCK)
1650 continue;
1651
1652 if (_BLOCK_TYPE(header->_block_use) == _CRT_BLOCK && (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF) == 0)
1653 continue;
1654
1655 if (header->_file_name != nullptr)
1656 {
1657 if (!_CrtIsValidPointer(header->_file_name, 1, FALSE) || is_bad_read_pointer(header->_file_name, 1))
1658 {
1659 _RPTN(_CRT_WARN, "#File Error#(%d) : ", header->_line_number);
1660 }
1661 else
1662 {
1663 _RPTN(_CRT_WARN, "%hs(%d) : ", header->_file_name, header->_line_number);
1664 }
1665 }
1666
1667 _RPTN(_CRT_WARN, "{%ld} ", header->_request_number);
1668
1669 if (_BLOCK_TYPE(header->_block_use) == _CLIENT_BLOCK)
1670 {
1671 _RPTN(_CRT_WARN, "client block at 0x%p, subtype %x, %Iu bytes long.\n",
1673 _BLOCK_SUBTYPE(header->_block_use),
1674 header->_data_size);
1675
1677 {
1679 }
1680 else
1681 {
1683 }
1684 }
1685 else if (header->_block_use == _NORMAL_BLOCK)
1686 {
1687 _RPTN(_CRT_WARN, "normal block at 0x%p, %Iu bytes long.\n",
1689 header->_data_size);
1690
1692 }
1693 else if (_BLOCK_TYPE(header->_block_use) == _CRT_BLOCK)
1694 {
1695 _RPTN(_CRT_WARN, "crt block at 0x%p, subtype %x, %Iu bytes long.\n",
1697 _BLOCK_SUBTYPE(header->_block_use),
1698 header->_data_size);
1699
1701 }
1702 }
1703}
Definition: _locale.h:75
#define _IGNORE_BLOCK
Definition: crtdbg.h:69
#define _BLOCK_SUBTYPE(block)
Definition: crtdbg.h:64
static bool __cdecl is_bad_read_pointer(void const *const p, size_t const size)
Definition: debug_heap.cpp:206
static void __cdecl print_block_data(_locale_t const locale, _CrtMemBlockHeader *const header)

Referenced by _CrtMemDumpAllObjectsSince().

◆ free_dbg_nolock() [1/2]

free_dbg_nolock ( block  ,
actual_use   
)

◆ free_dbg_nolock() [2/2]

static void __cdecl free_dbg_nolock ( void *const  block,
int const  block_use 
)
throw (
)
static

Definition at line 849 of file debug_heap.cpp.

853{
855
856 if (block == nullptr)
857 return;
858
859 #if _UCRT_HEAP_MISMATCH_DETECTION && (defined _M_IX86 || defined _M_AMD64)
860
862 {
863 HANDLE const msvcrt_heap_handle = __acrt_get_msvcrt_heap_handle();
864 if (msvcrt_heap_handle)
865 {
866 if (HeapValidate(msvcrt_heap_handle, 0, block))
867 {
868 _RPT1(_CRT_WARN, "CRTHEAP: ucrt: Attempt to free a pointer (0x%p) that belongs to MSVCRT's private heap, not the process heap.\n", block);
869
870 #if _UCRT_HEAP_MISMATCH_BREAK
871 _CrtDbgBreak();
872 #endif // _UCRT_HEAP_MISMATCH_BREAK
873
874 #if _UCRT_HEAP_MISMATCH_RECOVERY
875 if (HeapFree(msvcrt_heap_handle, 0, block))
876 {
877 _RPT1(_CRT_WARN, "CRTHEAP: ucrt: Successfully free'd 0x%p\n", block);
878 return;
879 }
880 else
881 {
882 _RPT1(_CRT_ERROR, "CRTHEAP: ucrt: Unable to free 0x%p\n", block);
883 _CrtDbgBreak(); // Force break.
884 }
885 #endif // _UCRT_HEAP_MISMATCH_RECOVERY
886 }
887 }
888 }
889
890 #endif // _UCRT_HEAP_MISMATCH_DETECTION && (defined _M_IX86 || defined _M_AMD64)
891
892 // Check to ensure that the block was not allocated by _aligned routines
894 {
895 // We don't know (yet) where (file, linenum) block was allocated
896 _RPTN(_CRT_ERROR, "The Block at 0x%p was allocated by aligned routines, use _aligned_free()", block);
897 errno = EINVAL;
898 return;
899 }
900
901 // Forced failure handling
902 if (_pfnAllocHook && !_pfnAllocHook(_HOOK_FREE, block, 0, block_use, 0, nullptr, 0))
903 {
904 _RPT0(_CRT_WARN, "Client hook free failure.\n");
905 return;
906 }
907
908 // If this assertion fails, a bad pointer has been passed in. It may be
909 // totally bogus, or it may have been allocated from another heap. The
910 // pointer must have been allocated from the CRT heap.
912
913 // Get a pointer to memory block header:
915 _ASSERTE(is_block_type_valid(header->_block_use));
916
917 // If we didn't already check entire heap, at least check this object by
918 // verifying that its no-man's land areas have not been trashed:
920 {
922 {
923 if (header->_file_name)
924 {
925 _RPTN(_CRT_ERROR, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
926 "CRT detected that the application wrote to memory before start of heap buffer.\n"
928 block_use_names[_BLOCK_TYPE(header->_block_use)],
929 header->_request_number,
931 header->_file_name,
932 header->_line_number);
933 }
934 else
935 {
936 _RPTN(_CRT_ERROR, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
937 "CRT detected that the application wrote to memory before start of heap buffer.\n",
938 block_use_names[_BLOCK_TYPE(header->_block_use)],
939 header->_request_number,
941 }
942 }
943
945 {
946 if (header->_file_name)
947 {
948 _RPTN(_CRT_ERROR, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
949 "CRT detected that the application wrote to memory after end of heap buffer.\n"
951 block_use_names[_BLOCK_TYPE(header->_block_use)],
952 header->_request_number,
954 header->_file_name,
955 header->_line_number);
956 }
957 else
958 {
959 _RPTN(_CRT_ERROR, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
960 "CRT detected that the application wrote to memory after end of heap buffer.\n",
961 block_use_names[_BLOCK_TYPE(header->_block_use)],
962 header->_request_number,
964 }
965 }
966 }
967
968 // If this block was ignored when it was allocated, we can just free it:
969 if (header->_block_use == _IGNORE_BLOCK)
970 {
974 return;
975 }
976
977 // Ensure that we were called with the right block use. CRT blocks can be
978 // freed as NORMAL blocks.
979 _ASSERTE(header->_block_use == block_use || header->_block_use == _CRT_BLOCK && block_use == _NORMAL_BLOCK);
980
981 __acrt_current_allocations -= header->_data_size;
982
983 // Optionally reclaim memory:
985 {
986 // Unlink this allocation from the global linked list:
987 if (header->_block_header_next)
988 {
989 header->_block_header_next->_block_header_prev = header->_block_header_prev;
990 }
991 else
992 {
994 __acrt_last_block = header->_block_header_prev;
995 }
996
997 if (header->_block_header_prev)
998 {
999 header->_block_header_prev->_block_header_next = header->_block_header_next;
1000 }
1001 else
1002 {
1004 __acrt_first_block = header->_block_header_next;
1005 }
1006
1009 }
1010 else
1011 {
1012 header->_block_use = _FREE_BLOCK;
1013
1014 // Keep memory around as dead space:
1016 }
1017}
_ACRTIMP void __cdecl _free_base(_Pre_maybenull_ _Post_invalid_ void *_Block)
#define _HOOK_FREE
Definition: crtdbg.h:44
#define _CrtDbgBreak()
Definition: crtdbg.h:103
#define _RPT1
Definition: crtdbg.h:175
static size_t __acrt_current_allocations
Definition: debug_heap.cpp:122
static void __cdecl validate_heap_if_required_nolock()
Definition: debug_heap.cpp:262
static _CrtMemBlockHeader * __acrt_last_block
Definition: debug_heap.cpp:115
static long const request_number_for_ignore_blocks
Definition: debug_heap.cpp:69
static bool __cdecl is_block_an_aligned_allocation(void const *const block)
Definition: debug_heap.cpp:249
static int const line_number_for_ignore_blocks
Definition: debug_heap.cpp:70
#define HeapFree(x, y, z)
Definition: compat.h:735

◆ header_from_block()

static _CrtMemBlockHeader *__cdecl header_from_block ( void const *const  block)
throw (
)
static

◆ heap_alloc_dbg()

static void *__cdecl heap_alloc_dbg ( size_t const  size,
int const  block_use,
char const *const  file_name,
int const  line_number 
)
throw (
)
static

Definition at line 445 of file debug_heap.cpp.

451{
452 bool const should_call_new_handler{_query_new_mode() != 0};
453 for (;;)
454 {
456 if (block)
457 return block;
458
459 if (!should_call_new_handler || !_callnewh(size))
460 {
461 errno_t* const global_errno{_errno()};
462 if (global_errno)
463 *global_errno = ENOMEM;
464
465 return nullptr;
466 }
467
468 // The new handler was successful -- try to allocate again
469 }
470}
_Check_return_ _ACRTIMP int __cdecl _callnewh(_In_ size_t _Size)
static void *__cdecl heap_alloc_dbg_internal(size_t const size, int const block_use, char const *const file_name, int const line_number)
Definition: debug_heap.cpp:304
_CRTIMP int *__cdecl _errno(void)
Definition: errno.c:17
int errno_t
Definition: corecrt.h:615
_ACRTIMP int __cdecl _query_new_mode(void)
Definition: heap.c:217

◆ heap_alloc_dbg_internal()

static void *__cdecl heap_alloc_dbg_internal ( size_t const  size,
int const  block_use,
char const *const  file_name,
int const  line_number 
)
throw (
)
static

Definition at line 304 of file debug_heap.cpp.

310{
311 void* block{nullptr};
312
314 __try
315 {
317
318 long const request_number{__acrt_current_request_number};
319
320 // Handle break-on-request and forced failure:
321 if (_crtBreakAlloc != -1 && request_number == _crtBreakAlloc)
322 {
323 _CrtDbgBreak();
324 }
325
328 nullptr,
329 size,
330 block_use,
331 request_number,
332 reinterpret_cast<unsigned char const*>(file_name),
334 {
335 if (file_name)
336 _RPTN(_CRT_WARN, "Client hook allocation failure at file %hs line %d.\n", file_name, line_number);
337 else
338 _RPT0(_CRT_WARN, "Client hook allocation failure.\n");
339
340 __leave;
341 }
342
343#pragma warning(suppress:__WARNING_UNUSED_ASSIGNMENT) // 28931
344 bool const ignore_block{_BLOCK_TYPE(block_use) != _CRT_BLOCK && !(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF)};
345
346 // Diagnostic memory allocation from this point on...
347 if (size > static_cast<size_t>(_HEAP_MAXREQ - no_mans_land_size - sizeof(_CrtMemBlockHeader)))
348 {
349 errno_t* const global_errno{_errno()};
350 if (global_errno)
351 *global_errno = ENOMEM;
352
353 __leave;
354 }
355
357 {
358 _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
359 }
360
361 size_t const block_size{sizeof(_CrtMemBlockHeader) + size + no_mans_land_size};
362
364 if (!header)
365 {
366 errno_t* const global_errno{_errno()};
367 if (global_errno)
368 *global_errno = ENOMEM;
369
370 __leave;
371 }
372
373 // Commit the allocation by linking the block into the global list:
375
376 if (ignore_block)
377 {
378 header->_block_header_next = nullptr;
379 header->_block_header_prev = nullptr;
380 header->_file_name = nullptr;
382 header->_data_size = size;
383 header->_block_use = _IGNORE_BLOCK;
384 header->_request_number = request_number_for_ignore_blocks;
385 }
386 else
387 {
388 // Keep track of total amount of memory allocated:
390 {
392 }
393 else
394 {
396 }
397
399
402
404 {
406 }
407 else
408 {
410 }
411
412 header->_block_header_next = __acrt_first_block;
413 header->_block_header_prev = nullptr;
414 header->_file_name = file_name;
415 header->_line_number = line_number;
416 header->_data_size = size;
417 header->_block_use = block_use;
418 header->_request_number = request_number;
419
421 }
422
423 // Fill the gap before and after the data block:
426
427 // Fill the data block with a silly (but non-zero) value:
429
431 }
433 {
435 }
437
438 return block;
439}
#define _HOOK_ALLOC
Definition: crtdbg.h:42
_CrtMemBlockHeader *const header
size_t size
static unsigned char const clean_land_fill
Definition: debug_heap.cpp:62
#define HeapAlloc
Definition: compat.h:733
#define SIZE_MAX
Definition: compat.h:66
_CrtMemBlockHeader * _block_header_prev
Definition: debug_heap.cpp:86
#define const
Definition: zconf.h:233

Referenced by heap_alloc_dbg().

◆ if() [1/4]

if ( new_block)

Definition at line 2998 of file btrfs.c.

2998 {
2999 ERR("out of memory\n");
3001 }
#define ERR(fmt,...)
Definition: precomp.h:57
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

◆ if() [2/4]

if ( block  )

◆ if() [3/4]

if ( )

Definition at line 798 of file debug_heap.cpp.

799 {
800 memset(
801 static_cast<unsigned char*>(new_block) + old_allocation_size,
802 0,
804 }

◆ if() [4/4]

if ( requested_size  ,
static_cast< size_t _HEAP_MAXREQ - no_mans_land_size - sizeof(_CrtMemBlockHeader) 
)

Definition at line 824 of file debug_heap.cpp.

825 {
826 errno = ENOMEM;
827 return nullptr;
828 }

◆ is_bad_read_pointer()

static bool __cdecl is_bad_read_pointer ( void const *const  p,
size_t const  size 
)
throw (
)
static

Definition at line 206 of file debug_heap.cpp.

207{
208 SYSTEM_INFO system_info{};
209 GetSystemInfo(&system_info);
210 DWORD const page_size{system_info.dwPageSize};
211
212 // If the structure has zero length, then do not probe the structure for
213 // read accessibility or alignment.
214 if (size == 0)
215 return false;
216
217 // A null pointer can never be read from:
218 if (!p)
219 return true;
220
221 char const* start_address{static_cast<char const*>(p)};
222 char const* end_address {start_address + size - 1 };
223 if (end_address < start_address)
224 return true;
225
226 __try
227 {
228 *(volatile char*)start_address;
229
230 long const mask{~(static_cast<long>(page_size) - 1)};
231
232 start_address = reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(start_address) & mask);
233 end_address = reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(end_address) & mask);
234 while (start_address != end_address)
235 {
236 start_address = start_address + page_size;
237 *reinterpret_cast<const volatile char*>(start_address);
238 }
239 }
241 {
242 return true;
243 }
245
246 return false;
247}
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLint GLuint mask
Definition: glext.h:6028
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
static DWORD page_size
Definition: loader.c:53
#define __except
Definition: pseh2_64.h:173

Referenced by dump_all_object_since_nolock().

◆ is_block_an_aligned_allocation()

static bool __cdecl is_block_an_aligned_allocation ( void const *const  block)
throw (
)
static

Definition at line 249 of file debug_heap.cpp.

250{
251 unsigned char const* const possible_alignment_gap{reinterpret_cast<unsigned char const*>(
252 reinterpret_cast<uintptr_t>(block) & (~sizeof(uintptr_t) - 1)) - align_gap_size};
253
254 return check_bytes(possible_alignment_gap, align_land_fill, align_gap_size);
255}

Referenced by free_dbg_nolock(), and realloc_dbg_nolock().

◆ is_block_type_valid()

static bool __cdecl is_block_type_valid ( int const  block_use)
throw (
)
static

◆ print_block_data()

static void __cdecl print_block_data ( _locale_t const  locale,
_CrtMemBlockHeader *const  header 
)
throw (
)
static

Definition at line 1609 of file debug_heap.cpp.

1613{
1614 _LocaleUpdate locale_update{locale};
1615
1616 static size_t const max_print = 16;
1617
1618 char print_buffer[max_print + 1];
1619 char value_buffer[max_print * 3 + 1];
1620
1621 size_t i{0};
1622 for (; i < min(header->_data_size, max_print); ++i)
1623 {
1624 unsigned char const c{block_from_header(header)[i]};
1625
1626 print_buffer[i] = _isprint_l(c, locale_update.GetLocaleT()) ? c : ' ';
1627 _ERRCHECK_SPRINTF(sprintf_s(value_buffer + i * 3, _countof(value_buffer) - (i * 3), "%.2X ", c));
1628 }
1629
1630 print_buffer[i] = '\0';
1631 _RPTN(_CRT_WARN, " Data: <%s> %s\n", print_buffer, value_buffer);
1632}
#define _ERRCHECK_SPRINTF(_PrintfCall)
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define _isprint_l(_Char, _Locale)
Definition: ctype.h:651
#define c
Definition: ke_i.h:80
#define min(a, b)
Definition: monoChain.cc:55
#define _countof(array)
Definition: sndvol32.h:70

Referenced by dump_all_object_since_nolock().

◆ realloc_dbg_nolock()

static void *__cdecl realloc_dbg_nolock ( void *const  block,
size_t *const  new_size,
int const  block_use,
char const *const  file_name,
int const  line_number,
bool const  reallocation_is_allowed 
)
throw (
)
static

Definition at line 535 of file debug_heap.cpp.

543{
544 // realloc(nullptr, size) is equivalent to malloc(size):
545 if (!block)
546 {
548 }
549
550 // realloc(block, 0) is equivalent to free(block):
551 if (reallocation_is_allowed && *new_size == 0)
552 {
554 return nullptr;
555 }
556
558
559 // Handle break-on-request and forced failure:
560 long const request_number{__acrt_current_request_number};
561 if (_crtBreakAlloc != -1 && request_number == _crtBreakAlloc)
562 {
563 _CrtDbgBreak();
564 }
565
568 block,
569 *new_size,
570 block_use,
571 request_number,
572 reinterpret_cast<unsigned char const*>(file_name),
574 {
575 if (file_name)
576 _RPTN(_CRT_WARN, "Client hook re-allocation failure at file %hs line %d.\n", file_name, line_number);
577 else
578 _RPT0(_CRT_WARN, "Client hook re-allocation failure.\n");
579
580 return nullptr;
581 }
582
583 // Ensure the block type matches what is expected and isn't an aligned allocation:
585 {
586 if (file_name)
587 {
589 "Error: memory allocation: bad memory block type.\n" _ALLOCATION_FILE_LINENUM,
591 }
592 else
593 {
594 _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
595 }
596 }
598 {
599 // We don't know (yet) where (file, linenum) block was allocated
600 _RPTN(_CRT_ERROR, "The Block at 0x%p was allocated by aligned routines, use _aligned_realloc()", block);
601 errno = EINVAL;
602
603 return nullptr;
604 }
605
606 // If this assertion fails, a bad pointer has been passed in. It may be
607 // totally bogus, or it may have been allocated from another heap. The
608 // pointer must have been allocated from the debug heap.
610
612
613 bool const is_ignore_block{old_head->_block_use == _IGNORE_BLOCK};
614 if (is_ignore_block)
615 {
616 _ASSERTE(old_head->_line_number == line_number_for_ignore_blocks && old_head->_request_number == request_number_for_ignore_blocks);
617 }
618 else if (__acrt_total_allocations < old_head->_data_size)
619 {
620 _RPTN(_CRT_ERROR, "Error: possible heap corruption at or near 0x%p", block);
621 errno = EINVAL;
622 return nullptr;
623 }
624
625 // Ensure the new requested size is not too large:
626 if (*new_size > static_cast<size_t>(_HEAP_MAXREQ - no_mans_land_size - sizeof(_CrtMemBlockHeader)))
627 {
628 errno = ENOMEM;
629 return nullptr;
630 }
631
632 // Note that all header values will remain valid and the minimum of the old
633 // size and the new size of data will remain valid.
634 size_t const new_internal_size{sizeof(_CrtMemBlockHeader) + *new_size + no_mans_land_size};
635
636 _CrtMemBlockHeader* new_head{nullptr};
637 if (reallocation_is_allowed)
638 {
639 new_head = static_cast<_CrtMemBlockHeader*>(_realloc_base(old_head, new_internal_size));
640 if (!new_head)
641 return nullptr;
642 }
643 else
644 {
645 new_head = static_cast<_CrtMemBlockHeader*>(_expand_base(old_head, new_internal_size));
646 if (!new_head)
647 return nullptr;
648
649 // On Win64, the heap does not try to resize the block if it is shrinking
650 // because of the use of the low-fragmentation heap. It just returns the
651 // original block. We make sure that our own header tracks that properly:
652 #ifdef _WIN64
653 *new_size = static_cast<size_t>(HeapSize(__acrt_heap, 0, new_head)
654 - sizeof(_CrtMemBlockHeader)
656 #endif
657 }
658
659 _Analysis_assume_(new_head->_data_size == old_head->_data_size);
660
661 // Account for the current allocation and track the total amount of memory
662 // that is currently allocated:
664 if (!is_ignore_block)
665 {
667 {
668 __acrt_total_allocations -= new_head->_data_size;
670 ? *new_size
671 : SIZE_MAX;
672 }
673
674 __acrt_current_allocations -= new_head->_data_size;
676
679 }
680
681 unsigned char* const new_block{block_from_header(new_head)};
682
683 // If the block grew, fill the "extension" with the land fill value:
684 if (*new_size > new_head->_data_size)
685 {
686 memset(new_block + new_head->_data_size, clean_land_fill, *new_size - new_head->_data_size);
687 }
688
689 // Fill in the gap after the client block:
691
692 if (!is_ignore_block)
693 {
694 new_head->_file_name = file_name;
695 new_head->_line_number = line_number;
696 new_head->_request_number = request_number;
697 }
698
699 new_head->_data_size = *new_size;
700
701 _ASSERTE(reallocation_is_allowed || (!reallocation_is_allowed && new_head == old_head));
702
703 // If the block did not move or is ignored, we are done:
704 if (new_head == old_head || is_ignore_block)
705 return new_block;
706
707 // Swap out the old block from the linked list and link in the new block:
708 if (new_head->_block_header_next)
709 {
710 new_head->_block_header_next->_block_header_prev = new_head->_block_header_prev;
711 }
712 else
713 {
714 _ASSERTE(__acrt_last_block == old_head);
716 }
717
718 if (new_head->_block_header_prev)
719 {
721 }
722 else
723 {
724 _ASSERTE(__acrt_first_block == old_head);
726 }
727
729 {
731 }
732 else
733 {
734 __acrt_last_block = new_head;
735 }
736
738 new_head->_block_header_prev = nullptr;
739 __acrt_first_block = new_head;
740
741 return new_block;
742}
#define _HOOK_REALLOC
Definition: crtdbg.h:43
size_t const new_size
Definition: expand.cpp:66
#define _Analysis_assume_
Definition: no_sal2.h:388
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)

◆ validate_heap_if_required_nolock()

static void __cdecl validate_heap_if_required_nolock ( )
throw (
)
static

Definition at line 262 of file debug_heap.cpp.

263{
264 if (__acrt_check_frequency == 0)
265 {
266 return;
267 }
268
270 {
272 return;
273 }
274
276 {
277 return;
278 }
279
281 __try
282 {
284 }
286 {
288 }
290
292}
static bool heap_validation_pending
Definition: debug_heap.cpp:260
int __cdecl _CrtCheckMemory()

Referenced by free_dbg_nolock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

Variable Documentation

◆ __acrt_check_counter

unsigned __acrt_check_counter {0}
static

Definition at line 128 of file debug_heap.cpp.

Referenced by _CrtSetDbgFlag(), and validate_heap_if_required_nolock().

◆ __acrt_check_frequency

unsigned __acrt_check_frequency {0}
static

Definition at line 127 of file debug_heap.cpp.

Referenced by _CrtSetDbgFlag(), and validate_heap_if_required_nolock().

◆ __acrt_current_allocations

size_t __acrt_current_allocations {0}
static

Definition at line 122 of file debug_heap.cpp.

Referenced by free_dbg_nolock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ __acrt_current_request_number

long __acrt_current_request_number {1}
static

Definition at line 132 of file debug_heap.cpp.

Referenced by _CrtIsMemoryBlock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ __acrt_first_block

◆ __acrt_last_block

_CrtMemBlockHeader* __acrt_last_block {nullptr}
static

Definition at line 115 of file debug_heap.cpp.

Referenced by free_dbg_nolock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ __acrt_max_allocations

size_t __acrt_max_allocations {0}
static

Definition at line 123 of file debug_heap.cpp.

Referenced by _CrtMemCheckpoint(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ __acrt_total_allocations

size_t __acrt_total_allocations {0}
static

Definition at line 121 of file debug_heap.cpp.

Referenced by _CrtMemCheckpoint(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ __finally

◆ __try

◆ _crtBreakAlloc

long _crtBreakAlloc {-1}

◆ _crtDbgFlag

◆ _pfnDumpClient

_CRT_DUMP_CLIENT _pfnDumpClient {nullptr}

◆ align_gap_size

◆ align_land_fill

◆ allocation_size

allocation_size {element_size * count}

Definition at line 518 of file debug_heap.cpp.

Referenced by cache_container_is_valid().

◆ block

◆ block_use

◆ block_use_names

char const* const block_use_names[_MAX_BLOCKS]
static
Initial value:
{
"Free",
"Normal",
"CRT",
"Ignore",
"Client",
}

Definition at line 33 of file debug_heap.cpp.

Referenced by _CrtMemDumpStatistics(), check_block(), and free_dbg_nolock().

◆ clean_land_fill

unsigned char const clean_land_fill {0xCD}
static

Definition at line 62 of file debug_heap.cpp.

Referenced by heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ count

Definition at line 781 of file debug_heap.cpp.

◆ dead_land_fill

unsigned char const dead_land_fill {0xDD}
static

Definition at line 61 of file debug_heap.cpp.

Referenced by check_block(), and free_dbg_nolock().

◆ element_size

◆ file_name

◆ header

◆ heap_validation_pending

bool heap_validation_pending {false}
static

Definition at line 260 of file debug_heap.cpp.

Referenced by validate_heap_if_required_nolock().

◆ line_number

◆ line_number_for_ignore_blocks

int const line_number_for_ignore_blocks {static_cast<int>(0xFEDCBABC)}
static

Definition at line 70 of file debug_heap.cpp.

Referenced by free_dbg_nolock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ new_allocation_size

size_t const new_allocation_size {element_size * count }

Definition at line 791 of file debug_heap.cpp.

Referenced by _aligned_offset_recalloc_dbg(), and if().

◆ new_block

◆ no_mans_land_fill

◆ no_mans_land_size

◆ old_allocation_size

size_t const old_allocation_size {block ? _msize_dbg(block, block_use) : 0}

Definition at line 790 of file debug_heap.cpp.

Referenced by _aligned_offset_recalloc_dbg(), and if().

◆ request_number_for_ignore_blocks

long const request_number_for_ignore_blocks {0}
static

Definition at line 69 of file debug_heap.cpp.

Referenced by free_dbg_nolock(), heap_alloc_dbg_internal(), and realloc_dbg_nolock().

◆ requested_size

size_t const requested_size

◆ size

Definition at line 1057 of file debug_heap.cpp.

Referenced by heap_alloc_dbg_internal().