📄 rmmmhomemade.c
字号:
if (pZone->pCSops!=NULL) pZone->pCSops->Leave(pZone->cs);#ifdef USE_LEAK_CHECKER if (pZone->recordLeaks) { RMRecordMallocLeakChecker (pZone->leakChecker, (void *)DataAddress(pCurrent,pZone->alignment), submittedSize); }#endif return (void *)DataAddress(pCurrent,pZone->alignment);}void *RMCallocInZone(RMuint32 zid,RMuint32 nmemb,RMuint32 size){ RMuint8 *beginning=(RMuint8 *)RMMallocInZone(zid,size*nmemb); RMMemset(beginning,0,size*nmemb); return (void *)beginning;}void RMFreeInZone(RMuint32 zid,void *ptr){ RMmemoryZone *pZone=&zones[zid]; memoryBlockHeader *pX; RMuint32 sizeOfX = 0; memoryBlockHeader *pCurrent,*pPrevious; memoryBlockHeader *pL=(memoryBlockHeader *)NULL,*pR=(memoryBlockHeader *)NULL; memoryBlockHeader **ppFirstFree=(memoryBlockHeader **)(&(pZone->pFirstFree)); if (pZone->pCSops!=NULL) pZone->pCSops->Enter(pZone->cs); if (!( (AmIBefore((memoryBlockHeader *)(pZone->beginning+HeaderSkip(pZone->alignment)-1), (memoryBlockHeader *)ptr) && AmIBefore((memoryBlockHeader *)ptr, (memoryBlockHeader *)(pZone->beginning+pZone->totalSize))) )) goto bad; // rewind to the memory block header. pX=(memoryBlockHeader *)(((RMuint8 *)ptr)-HeaderSkip(pZone->alignment)); sizeOfX=pX->size; // can we assume this is a valid block header? Let's check the hash. if (Hash((RMuint32)ptr,pX->size)!=pX->hash) goto bad; /************************************************************** Let's make eight cases: the block we want to free is pX. EMPTYFREELIST: the free block has no blocks. Make pX part of it. Over. BEFOREFIRSTNEIGHBOR: pX is the left neighbor of the first free block. Gather them (one block disappears). Over. BEFOREFIRST: pX is not the left neighbor, but is before the first free block. Make pX the first free block and link to the free block list. Over. Now, let's go thru the free block list: while (pCurrent) { pCurrent is a candidate to be left neighbor pL of pX and pCurrent->next a candidate to be the right neighbor pR of pX. MIDDLEBOTH: if we find both neighbors L and R, we gather pL, pX and pR (two blocks disappear). Over. MIDDLELEFT: if we find only the left neighbor L, we gather pL and pX (one block disappears). Over. MIDDLERIGHT: if we find only the right neighbor R, we gather pX and pR (one block disappears). Over. MIDDLENONE: if pCurrent->next exists and pCurrent < pX < pCurrent->next we cannot gather anything, but we insert this lonely block in the free list. Over. pPrevious=pCurrent; pCurrent=pCurrent->next; } If the loop exits, it means pX is after the last free block (his name is pPrevious). pX cannot be the right neighbor of pPrevious, because this case has been treated by case MIDDLELEFT. Only solution left: AFTERLAST: pX is not the right neighbor, but is after pPrevious. Make a new link. Over. All cases have been treated. **************************************************************/ // EMPTYFREELIST if (*ppFirstFree==NULL) { RMDBGLOG((MEMDBG,"RMFreeInZone: EMPTYFREELIST\n")); pX->hash=freeBlockHash; *ppFirstFree=pX; pX->next=(memoryBlockHeader *)NULL; goto returnok; } // BEFOREFIRSTNEIGHBOR if (AmILeftNeighbor(pX,*ppFirstFree,pZone->alignment)) { RMDBGLOG((MEMDBG,"RMFreeInZone: BEFOREFIRSTNEIGHBOR\n")); (*ppFirstFree)->hash=disappearedHash; pX->hash=freeBlockHash; pX->next=(*ppFirstFree)->next; pX->size+=HeaderSkip(pZone->alignment)+(*ppFirstFree)->size; *ppFirstFree=pX; goto returnok; } // BEFOREFIRST if (AmIBefore(pX,*ppFirstFree)) { RMDBGLOG((MEMDBG,"RMFreeInZone: BEFOREFIRST\n")); pX->hash=freeBlockHash; pX->next=*ppFirstFree; *ppFirstFree=pX; goto returnok; } pPrevious=(memoryBlockHeader *)NULL; pCurrent=*ppFirstFree; while (pCurrent) { /* notice that once one of pL or pR is not NULL we exit the while loop, so no need to reset them at each turn. */ // is pCurrent the left neighbor? if (AmILeftNeighbor(pCurrent,pX,pZone->alignment)) pL=pCurrent; // is pCurrent->next the right neighbor? if (pCurrent->next) if (AmILeftNeighbor(pX,pCurrent->next,pZone->alignment)) pR=pCurrent->next; // MIDDLEBOTH if (pL&&pR) { RMDBGLOG((MEMDBG,"RMFreeInZone: MIDDLEBOTH\n")); pX->hash=disappearedHash; pR->hash=disappearedHash; pL->next=pR->next; pL->size+=HeaderSkip(pZone->alignment)+pX->size +HeaderSkip(pZone->alignment)+pR->size; goto returnok; } // MIDDLELEFT if (pL) { RMDBGLOG((MEMDBG,"RMFreeInZone: MIDDLELEFT\n")); pX->hash=disappearedHash; pL->next=pCurrent->next; pL->size+=HeaderSkip(pZone->alignment)+pX->size; goto returnok; } // MIDDLERIGHT if (pR) { RMDBGLOG((MEMDBG,"RMFreeInZone: MIDDLERIGHT\n")); // pPrevious cannot be NULL (treated by BEFOREFIRSTNEIGHBOR case). pX->hash=freeBlockHash; pR->hash=disappearedHash; pCurrent->next=pX; pX->next=pR->next; pX->size+=HeaderSkip(pZone->alignment)+pR->size; goto returnok; } // MIDDLENONE if (pCurrent->next) if (AmIBefore(pCurrent,pX)&&AmIBefore(pX,pCurrent->next)) { RMDBGLOG((MEMDBG,"RMFreeInZone: MIDDLENONE\n")); pX->hash=freeBlockHash; pX->next=pCurrent->next; pCurrent->next=pX; goto returnok; } pPrevious=pCurrent; pCurrent=pCurrent->next; //RMDBGLOG((MEMDBG,"(RMFreeInZone: hop to next free block)\n")); } // AFTERLAST RMDBGLOG((MEMDBG,"RMFreeInZone: AFTERLAST\n")); pX->hash=freeBlockHash; // pPrevious->next cannot be NULL since there is at least one item in the free block list. pPrevious->next=pX; pX->next=(memoryBlockHeader *)NULL; goto returnok; bad: if (pZone->pCSops!=NULL) pZone->pCSops->Leave(pZone->cs); RMDBGLOG((ENABLE,"RMFreeInZone: bad pointer %p\n",ptr));#ifdef USE_LEAK_CHECKER RMPrintBackTrace (); if (pZone->recordLeaks) { RMRecordFreeLeakChecker (pZone->leakChecker, ptr); } #endif // USE_LEAK_CHECKER RMPanic(RM_FATALINVALIDPOINTER); returnok: pZone->successfulFrees++; pZone->occupiedSize-=sizeOfX;#ifdef TRASH_MEM trashMemory (ptr, sizeOfX);#endif // this is extremely serious. if (((pZone->successfulMallocs-pZone->successfulFrees)<0)||(pZone->occupiedSize<0)) { if (pZone->pCSops!=NULL) pZone->pCSops->Leave(pZone->cs);#ifdef USE_LEAK_CHECKER RMPrintBackTrace ();#endif RMPanic(RM_FATALMEMORYCORRUPTED); }#ifdef USE_LEAK_CHECKER if (pZone->recordLeaks) { RMRecordFreeLeakChecker (pZone->leakChecker, ptr); }#endif if (pZone->pCSops!=NULL) pZone->pCSops->Leave(pZone->cs);}void RMGetZoneStats(RMuint32 zid, RMuint32 *pSuccessfulMallocs, RMuint32 *pSuccessfulFrees, RMint32 *pOccupiedSize, RMint32 *pMaxSize){ RMmemoryZone *pZone=&zones[zid]; if (pSuccessfulMallocs!=NULL) *pSuccessfulMallocs=pZone->successfulMallocs; if (pSuccessfulFrees!=NULL) *pSuccessfulFrees=pZone->successfulFrees; if (pOccupiedSize!=NULL) *pOccupiedSize=pZone->occupiedSize; if (pMaxSize!=NULL) *pMaxSize=pZone->maxSize;}void RMDumpMallocedBlocksInZone(RMuint32 zid){ RMmemoryZone *pZone=&zones[zid]; memoryBlockHeader *pX; memoryBlockHeader *pCurrent; // allow negative numbers to trap corruption RMint32 computed_allocCount,computed_occupiedSize; memoryBlockHeader **ppFirstFree; computed_allocCount = 0; computed_occupiedSize = 0; ppFirstFree = (memoryBlockHeader **)(&(pZone->pFirstFree)); pX=(memoryBlockHeader *)(pZone->beginning); pCurrent=*ppFirstFree;#ifdef USE_LEAK_CHECKER RMPrintLeaksLeakChecker (pZone->leakChecker);#else // USE_LEAK_CHECKER RMDBGLOG((MEMDBG,"RMDumpMallocedBlocksInZone: allocCount=%ld occupiedSize=%ld\n", (pZone->successfulMallocs-pZone->successfulFrees), pZone->occupiedSize)); /* DOUBLE LOOP. pX goes thru candidates for occupied blocks (new pX is right neighbor of pX) pCurrent goes thru the linked list of free blocks as usual Focus attention on pX to understand the code. Let's start at the first possible pointer to an occupied block at the beginning of the zone */ while ( pX != (memoryBlockHeader *)(pZone->beginning+pZone->totalSize) ) { if (pX!=pCurrent) { // this must be an occupied block. // Let's check the hash. if (Hash((RMuint32)DataAddress(pX,pZone->alignment),pX->size)!=pX->hash) goto bad; RMDBGLOG((MEMDBG,"RMDumpMallocedBlocksInZone: occupied block #%3ld is (%p,%ld)\n", computed_allocCount, (void *)DataAddress(pX,pZone->alignment), pX->size)); computed_allocCount++; computed_occupiedSize+=pX->size; } else { RMDBGLOG((MEMDBG,"RMDumpMallocedBlocksInZone: skipping free block\n")); // this is a free block. pCurrent=pCurrent->next; } // compute right neighbor. pX=(memoryBlockHeader *)(DataAddress(pX,pZone->alignment)+pX->size); } if (computed_allocCount!=(RMint32)(pZone->successfulMallocs-pZone->successfulFrees)) goto bad; if (computed_occupiedSize!=pZone->occupiedSize) goto bad; RMDBGLOG((MEMDBG,"RMDumpMallocedBlocksInZone: seems memory is not corrupted :-)\n")); return; bad: RMPanic(RM_FATALMEMORYCORRUPTED);#endif // USE_LEAK_CHECKER}void *RMMalloc(RMuint32 submittedSize){ return RMMallocInZone(DEFAULT_MEMORY_ZONE,submittedSize);}void *RMCalloc(RMuint32 nmemb,RMuint32 size){ return RMCallocInZone(DEFAULT_MEMORY_ZONE,nmemb,size);}void RMFree(void *ptr){ RMFreeInZone(DEFAULT_MEMORY_ZONE,ptr);}#ifdef USE_LEAK_CHECKERvoid RMStartLeakCheckingInZone(RMuint32 zid){ RMmemoryZone *pZone=&zones[zid]; pZone->recordLeaks = TRUE;}void RMEndLeakCheckingInZone(RMuint32 zid){ RMmemoryZone *pZone=&zones[zid]; pZone->recordLeaks = FALSE;}#endif //USE_LEAK_CHECKER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -