2025-04-27 07:49:33 -04:00

324 lines
7.2 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
dbgheap.cpp
Abstract:
This module contains special debug versions of the new and delete
C++ operators.
The following functions are exported by this module:
operator new
operator delete
Author:
Keith Moore keithmo@microsoft.com 10-May-1996
Revision History:
--*/
#if DBG
extern "C" {
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
} // extern "C"
LIST_ENTRY SockHeapListHead;
ULONG SockTotalAllocations = 0;
ULONG SockTotalFrees = 0;
ULONG SockTotalBytesAllocated = 0;
RTL_RESOURCE SocketHeapLock;
BOOLEAN SockHeapDebugInitialized = FALSE;
BOOLEAN SockDebugHeap = FALSE;
PVOID SockHeap = NULL;
PVOID SockCaller1;
PVOID SockCaller2;
BOOLEAN SockDoHeapCheck = TRUE;
BOOLEAN SockDoubleHeapCheck = TRUE;
#define WINSOCK_HEAP_CODE_1 0xabcdef00
#define WINSOCK_HEAP_CODE_2 0x12345678
#define WINSOCK_HEAP_CODE_3 0x87654321
#define WINSOCK_HEAP_CODE_4 0x00fedcba
#define WINSOCK_HEAP_CODE_5 0xa1b2c3d4
#define MAX_STACK_BACKTRACE 3
//
// N.B. This header MUST be quadword aligned!
//
typedef struct _SOCK_HEAP_HEADER {
ULONG HeapCode1;
ULONG HeapCode2;
LIST_ENTRY GlobalHeapListEntry;
ULONG Size;
PVOID Stack[MAX_STACK_BACKTRACE];
} SOCK_HEAP_HEADER, *PSOCK_HEAP_HEADER;
typedef struct _SOCK_HEAP_TAIL {
PSOCK_HEAP_HEADER Header;
ULONG HeapCode3;
ULONG HeapCode4;
ULONG HeapCode5;
} SOCK_HEAP_TAIL, *PSOCK_HEAP_TAIL;
#define FREE_LIST_SIZE 64
SOCK_HEAP_HEADER SockRecentFreeList[FREE_LIST_SIZE];
ULONG SockRecentFreeListIndex = 0;
VOID
SockInitializeDebugData(
VOID
)
{
RtlInitializeResource( &SocketHeapLock );
InitializeListHead( &SockHeapListHead );
} // SockInitializeDebugData
VOID
SockCheckHeap(
VOID
)
{
PLIST_ENTRY listEntry;
PLIST_ENTRY lastListEntry = NULL;
PSOCK_HEAP_HEADER header;
SOCK_HEAP_TAIL UNALIGNED *tail;
if( !SockHeapDebugInitialized ) {
SockInitializeDebugData();
SockHeapDebugInitialized = TRUE;
}
if( !SockDoHeapCheck ) {
return;
}
RtlValidateHeap(
RtlProcessHeap(),
0,
NULL
);
RtlAcquireResourceExclusive(
&SocketHeapLock,
TRUE
);
for( listEntry = SockHeapListHead.Flink;
listEntry != &SockHeapListHead;
listEntry = listEntry->Flink ) {
if( listEntry == NULL ) {
DbgPrint( "listEntry == NULL, lastListEntry == %lx\n", lastListEntry );
DbgBreakPoint();
}
header = CONTAINING_RECORD( listEntry, SOCK_HEAP_HEADER, GlobalHeapListEntry );
tail = (SOCK_HEAP_TAIL UNALIGNED *)( (PCHAR)(header + 1) + header->Size );
if( header->HeapCode1 != WINSOCK_HEAP_CODE_1 ) {
DbgPrint( "SockCheckHeap, fail 1, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
if( header->HeapCode2 != WINSOCK_HEAP_CODE_2 ) {
DbgPrint( "SockCheckHeap, fail 2, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
if( tail->HeapCode3 != WINSOCK_HEAP_CODE_3 ) {
DbgPrint( "SockCheckHeap, fail 3, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
if( tail->HeapCode4 != WINSOCK_HEAP_CODE_4 ) {
DbgPrint( "SockCheckHeap, fail 4, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
if( tail->HeapCode5 != WINSOCK_HEAP_CODE_5 ) {
DbgPrint( "SockCheckHeap, fail 5, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
if( tail->Header != header ) {
DbgPrint( "SockCheckHeap, fail 6, header %lx tail %lx\n", header, tail );
DbgBreakPoint();
}
lastListEntry = listEntry;
}
RtlGetCallersAddress(
&SockCaller1,
&SockCaller2
);
RtlReleaseResource( &SocketHeapLock );
} // SockCheckHeap
PVOID
SockAllocateHeap(
IN ULONG NumberOfBytes
)
{
PSOCK_HEAP_HEADER header;
SOCK_HEAP_TAIL UNALIGNED *tail;
SockCheckHeap();
ASSERT( (NumberOfBytes & 0xF0000000) == 0 );
RtlAcquireResourceExclusive(
&SocketHeapLock,
TRUE
);
header = (PSOCK_HEAP_HEADER)RtlAllocateHeap(
RtlProcessHeap(),
0,
NumberOfBytes + sizeof(*header) + sizeof(*tail)
);
if( header == NULL ) {
RtlReleaseResource( &SocketHeapLock );
if( SockDoubleHeapCheck ) {
SockCheckHeap();
}
return NULL;
}
header->HeapCode1 = WINSOCK_HEAP_CODE_1;
header->HeapCode2 = WINSOCK_HEAP_CODE_2;
header->Size = NumberOfBytes;
tail = (SOCK_HEAP_TAIL UNALIGNED *)( (PCHAR)(header + 1) + NumberOfBytes );
tail->Header = header;
tail->HeapCode3 = WINSOCK_HEAP_CODE_3;
tail->HeapCode4 = WINSOCK_HEAP_CODE_4;
tail->HeapCode5 = WINSOCK_HEAP_CODE_5;
InsertTailList( &SockHeapListHead, &header->GlobalHeapListEntry );
SockTotalAllocations++;
SockTotalBytesAllocated += header->Size;
#if i386
{
ULONG hash;
RtlCaptureStackBackTrace(
2,
MAX_STACK_BACKTRACE,
(PVOID *)&header->Stack,
&hash
);
}
#endif // i386
RtlReleaseResource( &SocketHeapLock );
if( SockDoubleHeapCheck ) {
SockCheckHeap();
}
return (PVOID)(header + 1);
} // SockAllocateHeap
VOID
SockFreeHeap(
IN PVOID Pointer
)
{
PSOCK_HEAP_HEADER header = (PSOCK_HEAP_HEADER)Pointer - 1;
SOCK_HEAP_TAIL UNALIGNED * tail;
SockCheckHeap();
tail = (SOCK_HEAP_TAIL UNALIGNED *)( (PCHAR)(header + 1) + header->Size );
RtlAcquireResourceExclusive(
&SocketHeapLock,
TRUE
);
ASSERT( header->HeapCode1 == WINSOCK_HEAP_CODE_1 );
ASSERT( header->HeapCode2 == WINSOCK_HEAP_CODE_2 );
ASSERT( tail->HeapCode3 == WINSOCK_HEAP_CODE_3 );
ASSERT( tail->HeapCode4 == WINSOCK_HEAP_CODE_4 );
ASSERT( tail->HeapCode5 == WINSOCK_HEAP_CODE_5 );
ASSERT( tail->Header == header );
RemoveEntryList( &header->GlobalHeapListEntry );
SockTotalFrees++;
SockTotalBytesAllocated -= header->Size;
header->HeapCode1 = (ULONG)~WINSOCK_HEAP_CODE_1;
header->HeapCode2 = (ULONG)~WINSOCK_HEAP_CODE_2;
tail->HeapCode3 = (ULONG)~WINSOCK_HEAP_CODE_3;
tail->HeapCode4 = (ULONG)~WINSOCK_HEAP_CODE_4;
tail->HeapCode5 = (ULONG)~WINSOCK_HEAP_CODE_5;
tail->Header = NULL;
RtlReleaseResource( &SocketHeapLock );
RtlFreeHeap(
RtlProcessHeap(),
0,
(PVOID)header
);
if( SockDoubleHeapCheck ) {
SockCheckHeap();
}
} // SockFreeHeap
void *
__cdecl
operator new(
size_t size
)
{
return (void *)SockAllocateHeap( (ULONG)size );
} // operator new
void
__cdecl
operator delete(
void *ptr
)
{
SockFreeHeap( (PVOID)ptr );
} // operator delete
#endif // DBG