224 lines
4.8 KiB
C
224 lines
4.8 KiB
C
|
// dmalloc.c
|
||
|
//
|
||
|
|
||
|
#include "compact.h"
|
||
|
|
||
|
#define __DMALLOC_C__ 1 /* prevent redef of malloc et.al. */
|
||
|
|
||
|
#include "dmalloc.h" // public header file
|
||
|
#include "dmalloc_.h" // private header file
|
||
|
|
||
|
DMPRE dmprePrototype = {0x12345678, 0, 0, 0, 0, 0, 0, 0x9abcdef0};
|
||
|
DMSUF dmsufPrototype = {0x0fedcba9, 0x87654321};
|
||
|
|
||
|
void (*pfnDmallocError)(char *szReason, void *pvBadBlock);
|
||
|
int fDmallocInitialized = 0, fDmallocUsed = 0;
|
||
|
|
||
|
DMPRE dmpreLinkedListAnchor;
|
||
|
|
||
|
void
|
||
|
InitDmallocPfn(void (*pfnError)(char *szReason, void *pvBadBlock))
|
||
|
{
|
||
|
if (fDmallocUsed && !fDmallocInitialized)
|
||
|
(*pfnError)("can't initialize ... dmalloc already used", 0);
|
||
|
else {
|
||
|
fDmallocInitialized = 1;
|
||
|
pfnDmallocError = pfnError;
|
||
|
dmpreLinkedListAnchor.pdmpreNext = &dmpreLinkedListAnchor;
|
||
|
dmpreLinkedListAnchor.pdmprePrev = &dmpreLinkedListAnchor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
D_malloc(size_t cb)
|
||
|
{
|
||
|
DMPRE *pdmpre;
|
||
|
|
||
|
fDmallocUsed = 1;
|
||
|
if (!fDmallocInitialized)
|
||
|
return malloc(cb);
|
||
|
|
||
|
CheckDmallocHeap();
|
||
|
|
||
|
pdmpre = (DMPRE *)malloc(sizeof(DMPRE) + cb + sizeof(DMSUF));
|
||
|
if (pdmpre == 0)
|
||
|
return 0;
|
||
|
|
||
|
InitBlockPdmpre(pdmpre, cb);
|
||
|
|
||
|
return PvUserFromPdmpre(pdmpre);
|
||
|
}
|
||
|
|
||
|
void * D_calloc(size_t cElement, size_t cbElement)
|
||
|
{
|
||
|
void *pv;
|
||
|
|
||
|
fDmallocUsed = 1;
|
||
|
if (!fDmallocInitialized)
|
||
|
return calloc(cElement, cbElement);
|
||
|
|
||
|
CheckDmallocHeap();
|
||
|
|
||
|
pv = D_malloc(cElement * cbElement);
|
||
|
if (pv == 0)
|
||
|
return 0;
|
||
|
|
||
|
memset(pv, 0, cElement * cbElement);
|
||
|
|
||
|
return pv;
|
||
|
}
|
||
|
|
||
|
void * D_realloc(void *pv, size_t cb)
|
||
|
{
|
||
|
DMPRE *pdmpre;
|
||
|
DMSUF *pdmsuf;
|
||
|
|
||
|
fDmallocUsed = 1;
|
||
|
if (!fDmallocInitialized)
|
||
|
return realloc(pv, cb);
|
||
|
|
||
|
if (pv == 0)
|
||
|
return D_malloc(cb);
|
||
|
|
||
|
CheckDmallocHeap();
|
||
|
|
||
|
pdmpre = PdmpreFromPvUser(pv);
|
||
|
pdmsuf = (DMSUF *)((char *)pv + cb);
|
||
|
CheckBlockPdmpre(pdmpre);
|
||
|
ClearBlockPdmpre(pdmpre);
|
||
|
pdmpre = realloc(pdmpre, cb + sizeof(DMPRE) + sizeof(DMSUF));
|
||
|
if (pdmpre == 0)
|
||
|
return 0;
|
||
|
InitBlockPdmpre(pdmpre, cb);
|
||
|
|
||
|
return PvUserFromPdmpre(pdmpre);
|
||
|
}
|
||
|
|
||
|
void D_free(void *pv)
|
||
|
{
|
||
|
fDmallocUsed = 1;
|
||
|
if (!fDmallocInitialized) {
|
||
|
free(pv);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CheckDmallocHeap();
|
||
|
|
||
|
CheckBlockPdmpre(PdmpreFromPvUser(pv));
|
||
|
ClearBlockPdmpre(PdmpreFromPvUser(pv));
|
||
|
|
||
|
free(PdmpreFromPvUser(pv));
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
D_strdup(const char *szIn)
|
||
|
{
|
||
|
// We are counting bytes here so use strlen instead of _mbslen(), or
|
||
|
// any other _MBCS functions.
|
||
|
size_t cb = strlen(szIn) + 1;
|
||
|
char *szOut = D_malloc(cb);
|
||
|
|
||
|
_tcscpy(szOut, szIn);
|
||
|
return szOut;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
InitBlockPdmpre(DMPRE *pdmpre, size_t cbUser)
|
||
|
{
|
||
|
DMSUF UNALIGNED *pdmsuf = (DMSUF UNALIGNED *)((char *)PvUserFromPdmpre(pdmpre) + cbUser);
|
||
|
|
||
|
memcpy(pdmpre, &dmprePrototype, sizeof(DMPRE));
|
||
|
memcpy(pdmsuf, &dmsufPrototype, sizeof(DMSUF));
|
||
|
|
||
|
pdmpre->cbUser = cbUser;
|
||
|
pdmpre->ulNotCbUser = ~cbUser;
|
||
|
|
||
|
pdmpre->pdmpreCur = pdmpre;
|
||
|
|
||
|
pdmpre->pdmpreNext = dmpreLinkedListAnchor.pdmpreNext;
|
||
|
dmpreLinkedListAnchor.pdmpreNext->pdmprePrev = pdmpre;
|
||
|
UpdateLinksPdmpre(dmpreLinkedListAnchor.pdmpreNext);
|
||
|
|
||
|
pdmpre->pdmprePrev = &dmpreLinkedListAnchor;
|
||
|
dmpreLinkedListAnchor.pdmpreNext = pdmpre;
|
||
|
|
||
|
UpdateLinksPdmpre(pdmpre);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CheckBlockPdmpre(DMPRE *pdmpre)
|
||
|
{
|
||
|
DMPRE dmpreT;
|
||
|
DMSUF *pdmsuf, dmsufT;
|
||
|
void *pvUser;
|
||
|
|
||
|
pvUser = PvUserFromPdmpre(pdmpre);
|
||
|
|
||
|
if (pdmpre->cbUser != ~pdmpre->ulNotCbUser) {
|
||
|
(*pfnDmallocError)("dmalloc: block prefix (size) corrupted", pvUser);
|
||
|
return;
|
||
|
}
|
||
|
pdmsuf = (DMSUF *)((char *)pvUser + pdmpre->cbUser);
|
||
|
|
||
|
memcpy(&dmpreT, pdmpre, sizeof(DMPRE));
|
||
|
dmpreT.cbUser = dmpreT.ulNotCbUser = 0;
|
||
|
dmpreT.pdmpreNext = dmpreT.pdmprePrev = dmpreT.pdmpreCur = 0;
|
||
|
dmpreT.ulChecksum = 0;
|
||
|
|
||
|
if (memcmp(&dmpreT, &dmprePrototype, sizeof(DMPRE)) != 0) {
|
||
|
(*pfnDmallocError)("dmalloc: block prefix corrupted", pvUser);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memcpy(&dmsufT, pdmsuf, sizeof(DMSUF));
|
||
|
if (memcmp(&dmsufT, &dmsufPrototype, sizeof(DMSUF)) != 0) {
|
||
|
(*pfnDmallocError)("dmalloc: block suffix corrupted", pvUser);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (pdmpre->ulChecksum !=
|
||
|
((unsigned long)pdmpre->pdmpreNext ^
|
||
|
(unsigned long)pdmpre->pdmprePrev ^
|
||
|
~(unsigned long)pdmpre->pdmpreCur)) {
|
||
|
(*pfnDmallocError)("dmalloc: block prefix links corrupted", pvUser);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Things look OK.
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ClearBlockPdmpre(DMPRE *pdmpre)
|
||
|
{
|
||
|
DMSUF UNALIGNED *pdmsuf = (DMSUF UNALIGNED *)((char *)pdmpre + sizeof(DMPRE) + pdmpre->cbUser);
|
||
|
|
||
|
// Unhook it from the list.
|
||
|
//
|
||
|
pdmpre->pdmprePrev->pdmpreNext = pdmpre->pdmpreNext;
|
||
|
UpdateLinksPdmpre(pdmpre->pdmprePrev);
|
||
|
pdmpre->pdmpreNext->pdmprePrev = pdmpre->pdmprePrev;
|
||
|
UpdateLinksPdmpre(pdmpre->pdmpreNext);
|
||
|
|
||
|
memset(pdmpre, 0xbd, sizeof(DMPRE));
|
||
|
memset(pdmsuf, 0xbd, sizeof(DMSUF));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CheckDmallocHeap()
|
||
|
{
|
||
|
DMPRE *pdmpre;
|
||
|
|
||
|
pdmpre = &dmpreLinkedListAnchor;
|
||
|
while ((pdmpre = pdmpre->pdmpreNext) != &dmpreLinkedListAnchor) {
|
||
|
CheckBlockPdmpre(pdmpre);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
UpdateLinksPdmpre(DMPRE *pdmpre)
|
||
|
{
|
||
|
pdmpre->ulChecksum = (unsigned long)pdmpre->pdmpreNext ^
|
||
|
(unsigned long)pdmpre->pdmprePrev ^
|
||
|
~(unsigned long)pdmpre->pdmpreCur;
|
||
|
}
|