?? rmalloc.c
字號:
Return: New memory with copied string. Parameter: s string to copy file called from Purpose: Wrapper function for strdup() ============================================================================= */char *Rstrdup(const char *s, const char *file){ size_t size; /* needed memory */ char *ret; if (s == NULL) { fprintf(stderr, HEAD "Calling strdup(NULL) (in %s)\n", file); abort(); } size = strlen(s)+1; /* Rmalloc() does nearly all the work */ ret = Rmalloc(size, file); if (ret) { /* copy string */ strcpy(ret, s);#ifdef WITH_FLAGS Rmalloc_set_flags(ret, RM_STRING, "<by strdup>");#endif return ret; } else { fprintf(stderr, HEAD "WARNING: Out of memory! Returning NULL (in %s)\n", file); return NULL; }}/* ============================================================================= Function: Rgetcwd // external // Author: Rammi Date: 11/13/1998 Return: New memory with copied string depending on input (if buffer == NULL) Parameter: buffer buffer for write (or NULL) size buffer size file called from Purpose: Wrapper function for getcwd() which sometimes returns memory from heap. ============================================================================= */char *Rgetcwd(char *buffer, size_t size, const char *file){ char *ret = getcwd(buffer, size); if (ret && !buffer) { /* create new memory to get internals fixed */ char *newret = Rstrdup(ret, file); free(ret); /* free old stuff */ ret = newret; /* this was missing before 1.14 */ /* thanks to Greg Silverman who discovered it! */ } return ret;}/* ============================================================================= Function: Rmalloc_test // external // Author: Rammi Date: 04/11/1995 Return: --- Parameter: file called from Purpose: Explicitely test all blocks for integrity ============================================================================= */void Rmalloc_test(const char *file){#if RM_TEST_DEPTH > 0 TestAll(file);#else fprintf(stderr, HEAD __FILE__ " not compiled with RM_TEST_DEPTH > 0, call in %s senseless.\n", file);#endif}/* ============================================================================= Function: BlockSort // local // Author: Rammi Date: 04/15/1995 Return: < 0 A < B 0 A == B > 0 A > B Parameter: A, B Purpose: sort function for qsort ============================================================================= */static int BlockSort(const begin **A, const begin **B){ int ret; /* Sort for adress of string (tricky!) */ if ((ret = (*A)->File - (*B)->File)) { return ret; } /* sort for size */ return ((int)(*A)->Size - (int)(*B)->Size);}#ifdef GENERATIONS/* ============================================================================= Function: BlockSortGenerations // local // Author: Rammi Date: 04/22/2002 Return: < 0 A < B 0 A == B > 0 A > B Parameter: A, B Purpose: sort function for qsort, using the generations counter for sorting, too ============================================================================= */static int BlockSortGenerations(const begin **A, const begin **B){ int ret = BlockSort(A, B); if (ret) { return ret; } /* sort for generation */ return (*A)->Generation - (*B)->Generation;}#endif/* ============================================================================= Function: Rmalloc_stat // extern // Author: Rammi Date: 04/15/1995 Return: --- Parameter: file caled from Purpose: Show statistic ============================================================================= */void Rmalloc_stat(const char *file){#if RM_TEST_DEPTH > 0 TestAll(file);#define STAT_HEAD "<MALLOC_STATS>\t" fprintf(stderr,STAT_HEAD "============ STATISTICS (%s) =============\n", file); if (!Global.BlockCount) { fprintf(stderr, STAT_HEAD "Nothing allocated.\n"); } else { const begin **BlockVec; if ((BlockVec = (const begin **)malloc(Global.BlockCount*sizeof(begin *))) == NULL) { fprintf(stderr, STAT_HEAD "Couldn't allocate enough memory for statistics. Going on...\n"); } else { unsigned i = 0; unsigned j; begin *B; unsigned count; size_t Mem = 0; unsigned nrBlocks;#ifdef WITH_FLAGS size_t StaticMem = 0;#endif#ifdef GENERATIONS unsigned gen;#endif /* add all blocks to vector */ for (j = 0; j < HASHSIZE; j++) { for (B = Chain[j].Next; B != &Chain[j]; B = B->Next) {#ifdef WITH_FLAGS if (B->Flags & RM_STATIC) { StaticMem += B->Size; } else { BlockVec[i++] = B; }#else BlockVec[i++] = B;#endif } }#ifdef WITH_FLAGS assert(i <= Global.BlockCount);#else assert(i == Global.BlockCount);#endif nrBlocks = i; /* --- sort --- */#ifdef GENERATIONS qsort(BlockVec, nrBlocks, sizeof(begin *), (int (*)(const void *, const void *))BlockSortGenerations);#else qsort(BlockVec, nrBlocks, sizeof(begin *), (int (*)(const void *, const void *))BlockSort);#endif for (i = 0; i < nrBlocks; i = j) { count = 1; for (j = i+1; j < nrBlocks; j++) { if (BlockSort(BlockVec+i, BlockVec+j) != 0) { break; } /* are equal */ count++; }#ifdef GENERATIONS fprintf(stderr,STAT_HEAD "%6d x %8u Bytes in %s, generations:",count, (unsigned) BlockVec[i]->Size, BlockVec[i]->File); for (gen = 0; gen < count; gen++) { if (gen == MAX_STAT_GENERATIONS) { fprintf(stderr, " ..."); break; } fprintf(stderr, " %d", BlockVec[gen+i]->Generation); } fprintf(stderr, "\n");#else fprintf(stderr, STAT_HEAD "%6d x %8u Bytes in %s\n", count, (unsigned) BlockVec[i]->Size, BlockVec[i]->File);#endif Mem += count*BlockVec[i]->Size; } /* and give free */ free(BlockVec);#ifdef WITH_FLAGS fprintf(stderr, STAT_HEAD "*Variable*\t%12u Bytes\n", (unsigned) Mem); fprintf(stderr, STAT_HEAD "*Static* \t%12u Bytes\n", (unsigned) StaticMem); fprintf(stderr, STAT_HEAD "*Total* \t%12u Bytes\n", (unsigned) (Mem+StaticMem));#else fprintf(stderr, STAT_HEAD "*Total*\t%u Bytes\n", (unsigned) Mem);#endif } } fprintf(stderr, STAT_HEAD "============ END OF STATISTICS =============\n");#else fprintf(stderr, HEAD __FILE__ " not compiled with RM_TEST_DEPTH > 0, call in %s senseless.\n", file);#endif}void start_leak(void);void end_leak(void* file);const begin **BlockVec;unsigned befornr;void start_leak(){ TestAll("free all");#define STAT_HEAD "<MALLOC_STATS>\t" if (!Global.BlockCount) { fprintf(stderr, STAT_HEAD "Nothing allocated.\n"); } else { if ((BlockVec = (const begin **)malloc(Global.BlockCount*sizeof(begin *))) == NULL) { fprintf(stderr, STAT_HEAD "Couldn't allocate enough memory for statistics. Going on...\n"); } else { unsigned i = 0; unsigned j; begin *B; /* add all blocks to vector */ for (j = 0; j < HASHSIZE; j++) { for (B = Chain[j].Next; B != &Chain[j]; B = B->Next) { BlockVec[i++] = B; } } qsort(BlockVec, i, sizeof(begin *), (int (*)(const void *, const void *))BlockSortGenerations); befornr= i; } }}void end_leak(void* file){ TestAll("free all");#define STAT_HEAD "<MALLOC_STATS>\t" fprintf(stderr,STAT_HEAD "============ STATISTICS (%s) =============\n", "free all"); if (!Global.BlockCount) { fprintf(stderr, STAT_HEAD "Nothing allocated.\n"); } else { begin **BlockVec1; if ((BlockVec1 = (begin **)malloc(Global.BlockCount*sizeof(begin *))) == NULL) { fprintf(stderr, STAT_HEAD "Couldn't allocate enough memory for statistics. Going on...\n"); } else { unsigned i = 0; unsigned j; unsigned count; begin *B; unsigned nrBlocks; size_t mem = 0; /* add all blocks to vector */ for (j = 0; j < HASHSIZE; j++) { for (B = Chain[j].Next; B != &Chain[j]; B = B->Next) { BlockVec1[i++] = B; } } assert(i <= Global.BlockCount); nrBlocks = i; /* --- sort --- */ qsort(BlockVec1, nrBlocks, sizeof(begin *), (int (*)(const void *, const void *))BlockSortGenerations); for (i = 0; i < nrBlocks; i ++) { count = 0; for(j = 0 ; j < befornr; j++) { if((begin *)(((char *)BlockVec1[i])) == (begin *)(((char *)BlockVec[j]))) { { // printf("%s %s\n",(char*)file, BlockVec1[i]->File);} // (begin *)(((char *)BlockVec1[i])) = NULL; count = 1; break; } } } if(!count) { if(strstr(BlockVec1[i]->File, (char*)file) != 0) { mem += BlockVec1[i]->Size; fprintf(stderr,STAT_HEAD "%6d x %8u Bytes in %s\n", count, (unsigned) BlockVec1[i]->Size, BlockVec1[i]->File); DelBlk((begin *)(((char *)BlockVec1[i])),"free all"); free(((char *)BlockVec1[i])); // (begin *)(((char *)BlockVec1[i])) = NULL; } } // fprintf(stderr,STAT_HEAD "after %p\n", (begin *)(((char *)BlockVec1[i]))); // DelBlk((begin *)(((char *)BlockVec1[i])),"free all"); // free(((char *)BlockVec1[i])); } fprintf(stderr, STAT_HEAD "memory fried: %lu\n", mem); /* and give free */ free(BlockVec); free(BlockVec1); } } fprintf(stderr, STAT_HEAD "============ END OF STATISTICS =============\n");}void freeallall(){#if RM_TEST_DEPTH > 0 TestAll("free all");#define STAT_HEAD "<MALLOC_STATS>\t" fprintf(stderr,STAT_HEAD "============ STATISTICS (%s) =============\n", "free all"); if (!Global.BlockCount) { fprintf(stderr, STAT_HEAD "Nothing allocated.\n"); } else { begin **BlockVec; if ((BlockVec = (begin **)malloc(Global.BlockCount*sizeof(begin *))) == NULL) { fprintf(stderr, STAT_HEAD "Couldn't allocate enough memory for statistics. Going on...\n"); } else { unsigned i = 0; unsigned j; begin *B; unsigned count; size_t Mem = 0; unsigned nrBlocks;#ifdef WITH_FLAGS size_t StaticMem = 0;#endif#ifdef GENERATIONS unsigned gen;#endif /* add all blocks to vector */ for (j = 0; j < HASHSIZE; j++) { for (B = Chain[j].Next; B != &Chain[j]; B = B->Next) {#ifdef WITH_FLAGS if (B->Flags & RM_STATIC) { StaticMem += B->Size; } else { BlockVec[i++] = B; }#else BlockVec[i++] = B;#endif } }#ifdef WITH_FLAGS assert(i <= Global.BlockCount);#else assert(i == Global.BlockCount);#endif nrBlocks = i; fprintf(stderr,STAT_HEAD "non freed blocks %d\n" , nrBlocks); /* --- sort --- */#ifdef GENERATIONS qsort(BlockVec, nrBlocks, sizeof(begin *), (int (*)(const void *, const void *))BlockSortGenerations);#else qsort(BlockVec, nrBlocks, sizeof(begin *), (int (*)(const void *, const void *))BlockSort);#endif for (i = 0; i < nrBlocks; i = j) { count = 1; for (j = i+1; j < nrBlocks; j++) { if (BlockSort((const begin **)BlockVec+i, (const begin **)BlockVec+j) != 0) { break; } /* are equal */ count++; }#ifdef GENERATIONS fprintf(stderr,STAT_HEAD "%6d x %8u Bytes in %s, generations:",count, (unsigned) BlockVec[i]->Size, BlockVec[i]->File); for (gen = 0; gen < count; gen++) { if (gen == MAX_STAT_GENERATIONS) { fprintf(stderr, " ..."); break; } fprintf(stderr, " %d", BlockVec[gen+i]->Generation); } fprintf(stderr, "\n");#else fprintf(stderr, STAT_HEAD "%6d x %8u Bytes in %s\n", count, (unsigned) BlockVec[i]->Size, BlockVec[i]->File);#endif Mem += count*BlockVec[i]->Size; } for (i = 0; i < nrBlocks; i ++) { DelBlk((begin *)(((char *)BlockVec[i])),"free all"); free(((char *)BlockVec[i])); } /* and give free */ free(BlockVec);#ifdef WITH_FLAGS fprintf(stderr, STAT_HEAD "*Variable*\t%12u Bytes\n", (unsigned) Mem); fprintf(stderr, STAT_HEAD "*Static* \t%12u Bytes\n", (unsigned) StaticMem); fprintf(stderr, STAT_HEAD "*Total* \t%12u Bytes\n", (unsigned) (Mem+StaticMem));#else fprintf(stderr, STAT_HEAD "*Total*\t%u Bytes\n", (unsigned) Mem);#endif } } fprintf(stderr, STAT_HEAD "============ END OF STATISTICS =============\n");#else fprintf(stderr, HEAD __FILE__ " not compiled with RM_TEST_DEPTH > 0, call in %s senseless.\n", file);#endif}/* ============================================================================= Function: Rmalloc_retag // external // Author: Rammi Date: 12/12/1997 Return: the pointer p for possible chaining Parameter: p pointer to allocated block (user) file called from Purpose: Change file position in header. ============================================================================= */void * Rmalloc_retag(void *p, const char *file){ if (p) { begin *info = (begin *)(((char *)p)-START_SPACE); /* --- test integrity --- */ ControlBlock(info, file); /* --- change file pos --- */ info->File = file; } return p;}/* ============================================================================= Function: Rmalloc_set_flags // external // Author: Rammi Date: 12/12/1997 Return: the pointer p for possible chaining Parameter: p pointer to allocated block (user) flags Flags to set file called from Purpose: Set flags in header ============================================================================= */void *Rmalloc_set_flags(void *p, RMuint32 flags, const RMascii *file){#ifdef WITH_FLAGS if (p) { begin *info = (begin *)(((char *)p)-START_SPACE); /* --- test integrity --- */ ControlBlock(info, file); /* --- change flags --- */ info->Flags |= flags; }#endif return p;}/* ============================================================================= Function: Rmalloc_reinit // external // Author: Rammi Date: 05/28/1998 Return: --- Parameter: --- Purpose: This reinits the lists. This is only for test purposes. DON'T USE THIS FUNCTION! ============================================================================= */void Rmalloc_reinit(void){#if RM_TEST_DEPTH > 0 int i; /* --- init list heads (discarding everything!) --- */ for (i = 0; i < HASHSIZE; i++) { memcpy(Chain+i, &ChainTempl, sizeof(begin)); Chain[i].Next = Chain[i].Prev = Chain+i; }#endif#ifdef GENERATIONS cur_generation = 0;#endif}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -