329 lines
6.4 KiB
C++
329 lines
6.4 KiB
C++
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
dbgnewp.cxx
|
|
|
|
Abstract:
|
|
|
|
Debug new private file
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 23-June-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "dbgtag.hxx"
|
|
#include "dbgnewp.hxx"
|
|
|
|
TDebugNewAllocator::
|
|
TDebugNewAllocator(
|
|
VOID
|
|
) : m_bValid( FALSE ),
|
|
m_hDataHeap( NULL ),
|
|
m_pTag( NULL )
|
|
{
|
|
}
|
|
|
|
TDebugNewAllocator::
|
|
~TDebugNewAllocator(
|
|
VOID
|
|
)
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
BOOL
|
|
TDebugNewAllocator::
|
|
bValid(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_bValid;
|
|
}
|
|
|
|
|
|
VOID
|
|
TDebugNewAllocator::
|
|
Initialize(
|
|
IN UINT uSizeHint
|
|
)
|
|
{
|
|
m_pTag = INTERNAL_NEW TDebugNewTag();
|
|
|
|
m_hDataHeap = HeapCreate( 0, kDataHeapSize, 0 );
|
|
|
|
if (m_hDataHeap && m_pTag->bInit() )
|
|
{
|
|
m_bValid = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TDebugNewAllocator::
|
|
Destroy(
|
|
VOID
|
|
)
|
|
{
|
|
if (m_hDataHeap)
|
|
{
|
|
HeapDestroy( m_hDataHeap );
|
|
}
|
|
|
|
INTERNAL_DELETE m_pTag;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate a new memory block, tracking the allocation for
|
|
// leak detection.
|
|
//
|
|
PVOID
|
|
TDebugNewAllocator::
|
|
Allocate(
|
|
IN SIZE_T Size,
|
|
IN PVOID pVoid,
|
|
IN LPCTSTR pszFile,
|
|
IN UINT uLine
|
|
)
|
|
{
|
|
//
|
|
// Allocate the memory block.
|
|
//
|
|
Header *pHeader = reinterpret_cast<Header *>( HeapAlloc( m_hDataHeap,
|
|
0,
|
|
sizeof( Header ) + Size + sizeof( Tail ) ) );
|
|
//
|
|
// If the block was allocated successfully.
|
|
//
|
|
if (pHeader)
|
|
{
|
|
//
|
|
// Track this memory allocation.
|
|
//
|
|
if( m_pTag->Tag( &pHeader->pTag, pHeader, Size, pszFile, uLine ) )
|
|
{
|
|
//
|
|
// Set the header data and tail pattern. The tag back pointer is
|
|
// is set for efficent release, the data area is filled with a known pattern
|
|
// and tail is filled with a known pattern for overwrite detection.
|
|
//
|
|
FillHeaderDataTailPattern( pHeader, Size );
|
|
|
|
//
|
|
// Adjust returned pointer to client data area.
|
|
//
|
|
pHeader++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Tag entry was not available, something horrible happened.
|
|
// If this happens then clean up the allocation and
|
|
// return failure for this allocation.
|
|
//
|
|
HeapFree( m_hDataHeap, 0, pHeader );
|
|
pHeader = NULL;
|
|
}
|
|
}
|
|
|
|
return pHeader;
|
|
}
|
|
|
|
//
|
|
// Release the memory block, checking for duplicate frees and
|
|
// tail overwrites.
|
|
//
|
|
VOID
|
|
TDebugNewAllocator::
|
|
Release(
|
|
IN PVOID pVoid
|
|
)
|
|
{
|
|
//
|
|
// Convert the client data area pointer to header pointer.
|
|
//
|
|
Header *pHeader = reinterpret_cast<Header *>( pVoid ) - 1;
|
|
|
|
//
|
|
// Validate the header and tail signatures.
|
|
//
|
|
ValidationErrorCode ValidationError = ValidateHeaderDataTailPattern( pVoid, pHeader );
|
|
|
|
switch (ValidationError)
|
|
{
|
|
case kValidationErrorSuccess:
|
|
|
|
//
|
|
// Release allocation from tag list.
|
|
//
|
|
m_pTag->Release( pHeader->pTag );
|
|
|
|
//
|
|
// Release this block back to the heap.
|
|
//
|
|
HeapFree( m_hDataHeap, 0, pHeader );
|
|
break;
|
|
|
|
case kValidationErrorNullPointer:
|
|
//
|
|
// It is ok to attempt to free the null pointer.
|
|
//
|
|
break;
|
|
|
|
//
|
|
// We leak memory allocations that fail header, tail or tag validation.
|
|
//
|
|
case kValidationErrorInvalidHeader:
|
|
ErrorText( _T("Buffer failed header validation\n") );
|
|
break;
|
|
|
|
case kValidationErrorInvalidTail:
|
|
ErrorText( _T("Buffer failed tail validation\n") );
|
|
break;
|
|
|
|
case kValidationErrorUnknown:
|
|
default:
|
|
ErrorText( _T("Buffer failed validation\n") );
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TDebugNewAllocator::
|
|
Report(
|
|
IN UINT uDevice,
|
|
IN LPCTSTR pszConfiguration
|
|
) const
|
|
{
|
|
m_pTag->DisplayInuseTagEntries( uDevice, pszConfiguration );
|
|
}
|
|
|
|
/********************************************************************
|
|
|
|
Private member functions.
|
|
|
|
********************************************************************/
|
|
|
|
VOID
|
|
TDebugNewAllocator::
|
|
FillHeaderDataTailPattern(
|
|
IN Header *pHeader,
|
|
IN SIZE_T Size
|
|
)
|
|
{
|
|
//
|
|
// Fill the header pattern.
|
|
//
|
|
memset( &pHeader->pSignature, kHeaderPattern, sizeof( PVOID ) );
|
|
|
|
//
|
|
// Fill the Data pattern.
|
|
//
|
|
memset( ++pHeader, kDataAllocPattern, Size );
|
|
|
|
//
|
|
// Calculate the tail pointer.
|
|
//
|
|
Tail *pTail = reinterpret_cast<Tail *>( reinterpret_cast<PBYTE>( pHeader ) + Size );
|
|
|
|
//
|
|
// Write the tail pattern.
|
|
//
|
|
memset( &pTail->pSignature, kTailPattern, sizeof( PVOID ) );
|
|
}
|
|
|
|
TDebugNewAllocator::ValidationErrorCode
|
|
TDebugNewAllocator::
|
|
ValidateHeaderDataTailPattern(
|
|
IN PVOID pVoid,
|
|
IN Header *pHeader
|
|
)
|
|
{
|
|
if (!pVoid)
|
|
{
|
|
return kValidationErrorNullPointer;
|
|
}
|
|
|
|
//
|
|
// Validate the header pointer.
|
|
//
|
|
if (!pHeader)
|
|
{
|
|
return kValidationErrorInvalidHeaderPtr;
|
|
}
|
|
|
|
//
|
|
// Validate the header structure.
|
|
//
|
|
if (IsBadReadPtr( pHeader, sizeof( Header )))
|
|
{
|
|
return kValidationErrorInvalidHeader;
|
|
}
|
|
|
|
//
|
|
// Validate the header signature.
|
|
//
|
|
PVOID pTemp;
|
|
|
|
memset( &pTemp, kHeaderPattern, sizeof( PVOID ) );
|
|
|
|
if (pHeader->pSignature != pTemp)
|
|
{
|
|
return kValidationErrorInvalidHeaderSignature;
|
|
}
|
|
|
|
//
|
|
// Validate the tag entry.
|
|
//
|
|
switch (m_pTag->ValidateEntry( pHeader->pTag ))
|
|
{
|
|
case TDebugNewTag::kValidationErrorInvalidPointer:
|
|
break;
|
|
|
|
case TDebugNewTag::kValidationErrorInvalidHeader:
|
|
break;
|
|
|
|
case TDebugNewTag::kValidationErrorTagNotLinked:
|
|
break;
|
|
|
|
case TDebugNewTag::kValidationErrorUnknown:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the tail pointer.
|
|
//
|
|
Tail *pTail = reinterpret_cast<Tail *>( reinterpret_cast<PBYTE>(pHeader+1)+m_pTag->GetSize( pHeader->pTag ) );
|
|
|
|
//
|
|
// Validate the tail structure.
|
|
//
|
|
if (IsBadReadPtr( pTail, sizeof( Tail )))
|
|
{
|
|
return kValidationErrorInvalidTailPointer;
|
|
}
|
|
|
|
//
|
|
// Validate the tail signature.
|
|
//
|
|
memset( &pTemp, kTailPattern, sizeof( PVOID ) );
|
|
|
|
if( pTail->pSignature != pTemp )
|
|
{
|
|
return kValidationErrorInvalidTailSignature;
|
|
}
|
|
|
|
return kValidationErrorSuccess;
|
|
}
|
|
|