Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

265 lines
7.4 KiB

/*** mem.c - Memory Manager
*
* Microsoft Confidential
* Copyright (C) Microsoft Corporation 1993-1994
* All Rights Reserved.
*
* Author:
* Benjamin W. Slivka
*
* History:
* 10-Aug-1993 bens Initial version
* 11-Aug-1993 bens Lift code from STOCK.EXE win app
* 12-Aug-1993 bens Get strings from memory.msg
* 01-Sep-1993 bens Add NULL pointer checks to MMAssert and MMStrDup
* 18-Mar-1994 bens Make sure non-assert build works; rename
* 18-May-1994 bens Allow turning off MemCheckHeap() in debug build
* (it can really, really slow things down!)
*
* Functions:
* MemAlloc - Allocate memory block
* MemFree - Free memory block
* MemStrDup - Duplicate string to new memory block
*
* Functions available in ASSERT build:
* MemAssert - Assert that pointer was allocated by MemAlloc
* MemCheckHeap - Check entire memory heap
* MemListHeap - List all heap entries
* MemGetSize - Return allocated size of memory block
* MemSetCheckHeap - Control whether MemCheckHeap is done on every
* every MemAlloc and MemFree!
*/
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include "types.h"
#include "asrt.h"
#ifdef ASSERT // Must be after asrt.h!
#include "mem.h"
#include "mem.msg"
/*** MEMSIG - memory signature
*
* This is placed at the front and end of every dynamic memory
* alloction in DEBUG builds. The pointer has to be unaligned for
* RISC machines.
*/
typedef ULONG MEMSIG; /* ms - memory signature */
typedef MEMSIG UNALIGNED *PMEMSIG; /* pms */
#define msHEAD 0x12345678L // Head signature
#define msTAIL 0x87654321L // Tail signature
#define msBAD 0L // Bad signature
#define cmsTAIL 2 // Number of tail signatures
typedef struct mh_t {
MEMSIG ms; // Head signature (msHEAD)
unsigned cb; // Size of user block
struct mh_t *pmhNext; // Next block
struct mh_t *pmhPrev; // Previous block
// char ach[?]; // User block; length is cb
// MEMSIG ms[cmsTAIL]; // Tail signature area (msTAIL...)
} MEMHDR; /* mh - memory header */
typedef MEMHDR *PMEMHDR; /* pmh */
#define PMHFromPV(pv) ((PMEMHDR)((char *)pv - sizeof(MEMHDR)))
#define PVFromPMH(pmh) ((void *)((char *)pmh+sizeof(MEMHDR)))
STATIC PMEMHDR pmhList=NULL; // List of memory blocks
STATIC BOOL fDoCheckHeap=TRUE; // TRUE => check heap regularly
void MemSetCheckHeap(BOOL f)
{
fDoCheckHeap = f;
}
void MMCheckHeap(char *pszFile, int iLine)
{
PMEMHDR pmh;
PMEMHDR pmhPrev = NULL;
for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
MMAssert(PVFromPMH(pmh),pszFile,iLine);
AssertSub(pmh->pmhPrev==pmhPrev,pszFile,iLine);
pmhPrev = pmh;
}
}
void MMListHeap(char *pszFile, int iLine)
{
PMEMHDR pmh;
if (fDoCheckHeap) {
if (pmhList != NULL) {
printf("\n");
for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
printf("alloc at %08lX is %d bytes\n", PVFromPMH(pmh), pmh->cb);
}
MMCheckHeap(pszFile,iLine);
printf("\n");
}
}
}
void MMAssert(void *pv, char *pszFile, int iLine)
{
int i;
PMEMHDR pmh;
PMEMSIG pms;
AssertSub(pv!=NULL,pszFile,iLine);
pmh = PMHFromPV(pv);
if ((void *)pmh > pv) { // Pointer wrapped
AssertForce(pszMEMERR_NULL_POINTER,pszFile,iLine);
}
// Test head signature
if (pmh->ms != msHEAD) {
AssertForce(pszMEMERR_BAD_HEAD_SIG,pszFile,iLine);
}
// Test tail signatures
pms = (PMEMSIG)( (char *)pmh + sizeof(MEMHDR) + pmh->cb );
for (i=0; i<cmsTAIL; i++) {
if (*pms++ != msTAIL) {
AssertForce(pszMEMERR_BAD_HEAD_SIG,pszFile,iLine);
}
}
} /* MMAssert */
void MMFree(void *pv, char *pszFile, int iLine)
{
PMEMHDR pmh;
MMAssert(pv,pszFile,iLine);
//** Check heap if enabled
if (fDoCheckHeap) {
MMCheckHeap(pszFile,iLine);
}
pmh = PMHFromPV(pv);
// Make previous block point to next block
if (pmh->pmhPrev != NULL) { // pmh is not at front of list
// before: a->p->?
pmh->pmhPrev->pmhNext = pmh->pmhNext;
// after: a->?
}
else { // pmh is at front of list
// before: list->p->?
pmhList = pmh->pmhNext;
// after: list->?
}
// Make next block point to previous block
if (pmh->pmhNext != NULL) { // pmh is not at end of list
// before: ?<-p<->a
pmh->pmhNext->pmhPrev = pmh->pmhPrev;
// after: ?<-a
}
// Obliterate signature
pmh->ms = msBAD;
// Free memory
free((char *)pmh);
}
void *MMAlloc(unsigned cb, char *pszFile, int iLine)
{
unsigned cbAlloc;
int i;
PMEMHDR pmh;
PMEMSIG pms;
if (fDoCheckHeap) {
MMCheckHeap(pszFile,iLine);
}
// Solves alignment problems on the RISCs
cb = (cb+3) & ~3;
cbAlloc = cb+sizeof(MEMHDR)+sizeof(MEMSIG)*cmsTAIL;
pmh = malloc(cbAlloc);
if (pmh != NULL) {
pmh->ms = msHEAD; // Store head signature
pmh->cb = cb; // Store size of user block
// Add block to front of list (Easiest code!)
if (pmhList != NULL) { // List is not empty
pmhList->pmhPrev = pmh; // Point old top block back at us
}
pmh->pmhNext = pmhList; // Next element is old top block
pmh->pmhPrev = NULL; // We are first, so no prev block
pmhList = pmh; // Make ourselves first
// Fill in tail signatures
pms = (PMEMSIG)( (char *)pmh + sizeof(MEMHDR) + pmh->cb );
for (i=0; i<cmsTAIL; i++) {
*pms++ = msTAIL;
}
return PVFromPMH(pmh);
}
else {
AssertForce(pszMEMERR_OUT_OF_MEMORY,pszFile,iLine);
/*
printf("panic: out of memory in MMAlloc\n");
printf("\n");
printf("Dump of heap (newest alloc to oldest)\n");
printf("\n");
printf("Size Addr Content\n");
printf("----- ---- -------\n");
for (pmh = pmhList; pmh != NULL; pmh = pmh->pmhNext) {
pch = PVFromPMH(pmh);
printf("%5d %04x %s\n",pmh->cb,(unsigned)pch,pch);
}
return NULL;
*/
}
}
char *MMStrDup(char *pch, char *pszFile, int iLine)
{
unsigned cb;
char *pchDst;
//** Make sure pointer is not null.
// NOTE: pch does not have to be a string we dynamically allocated!
AssertSub(pch!=NULL,pszFile,iLine);
cb = strlen(pch)+1; // Count NUL terminator
pchDst = MMAlloc(cb,pszFile,iLine); // Alloc new copy
if (pchDst != NULL) { // Success
memcpy(pchDst,pch,cb); // Copy string
}
return pchDst; // Return string copy
}
int MemGetSize(void *pv)
{
PMEMHDR pmh;
MMAssert(pv,__FILE__,__LINE__);
pmh = PMHFromPV(pv);
return pmh->cb;
}
#endif // !ASSERT