📄 malloc.c
字号:
struct mhdr *mptr;
cp = _calloc(nelem, elsize);
if (cp) {
mptr = (struct mhdr *)cp;
mptr--;
strncpy(mptr->fname,fname,FNAMESIZE-1);
mptr->fline = fline;
mptr->fname[FNAMESIZE-1] = 0;
mptr->fline = fline;
}
return(cp);
}
#else
char *
calloc(int nelem, int elsize)
{
return(_calloc(nelem,elsize));
}
#endif
static char *
_realloc(char *cp,int newsize)
{
char *new;
int asize, delta;
struct mhdr *mptr, tmphdr;
rcalls++;
/* If incoming pointer is NULL, then do a regular malloc. */
if (!cp)
return(_malloc(newsize));
/* If newsize is zero and pointer is not null, then do a free. */
if (!newsize) {
free(cp);
return((char *)0);
}
/* Set the mhdr pointer to the header attached to the incoming
* char pointer. We assume here that the incoming pointer is the
* base address of the block of memory that is being reallocated.
*/
mptr = (struct mhdr *)cp - 1;
/* Start by checking sanity of heap and make sure that the incoming
* pointer corresponds to a valid entry in the heap.
*/
if (heapcheck(mptr,0) < 0)
return((char *)0);
/* Recall that mptr->size is negative since the block is not free, so
* use the absolute value of mptr->size...
*/
asize = abs(mptr->size);
/* Make requested size divisible by 4:
*/
if (newsize & 3) {
newsize += 4;
newsize &= 0xfffffffc;
}
/* If newsize is less than or equal to current size, just return with
* the same pointer. At some point, this should be improved so that
* the memory made made available by this reallocation is put back in
* the pool.
*/
if (newsize <= asize)
return(cp);
/* Now we do the actual reallocation...
* If there is a fragment after this one (next != NULL) AND it is
* available (size > 0) AND the combined size of the next fragment
* along with the current fragment exceeds the request, then we can
* reallocate quickly.
* Otherwise, we have to just malloc a whole new block and copy the
* old buffer to the new larger space.
*/
if ((mptr->next) && (mptr->next->size > 0) &&
((asize + mptr->next->size + MHDRSIZE) > newsize)) {
/* At this point we know we have the space to reallocate without
* the malloc/free step. Now we need to add the necessary space
* to the current fragment, and take that much away from the next
* fragment...
*/
delta = newsize - asize;
tmphdr = *mptr->next;
mptr->size = -newsize;
mptr->next = (struct mhdr *)(delta + (int)(mptr->next));
mptr->next->size = (abs(tmphdr.size) - delta);
mptr->next->pretag = PRETAG;
mptr->next->posttag = POSTTAG;
mptr->next->next = tmphdr.next;
mptr->next->prev = tmphdr.prev;
/* Keep track of totals and highwater:
*/
mtot += (newsize - asize);
if ((mtot - ftot) > highwater)
highwater = (mtot - ftot);
return(cp);
}
/* If the next fragment is not large enough, then malloc new space,
* copy the existing data to that block, free the old space and return
* a pointer to the new block.
*/
new = _malloc(newsize);
if (!new)
return((char *)0);
memcpy(new,cp,asize);
free(cp);
return(new);
}
#ifdef MALLOC_DEBUG
#undef realloc
char *
realloc(char *buf, int newsize, char *fname, int fline)
{
char *cp;
struct mhdr *mptr;
cp = _realloc(buf, newsize);
if (cp) {
mptr = (struct mhdr *)cp;
mptr--;
strncpy(mptr->fname,fname,FNAMESIZE-1);
mptr->fline = fline;
mptr->fname[FNAMESIZE-1] = 0;
mptr->fline = fline;
}
return(cp);
}
#else
char *
realloc(char *buf, int newsize)
{
return(_realloc(buf,newsize));
}
#endif
void
heapdump(int verbose)
{
register struct mhdr *mptr;
char freenow;
int i, alloctot, freetot, size;
heapcheck(0,0);
mptr = heapbase;
i=0;
freetot = 0;
alloctot = 0;
if (verbose)
printf(" addr size free? mptr nxt prv ascii@addr\n");
else
printf("Heap summary:\n");
for(i=0;mptr;i++) {
if (mptr->size < 0) {
freenow = 'n';
size = -mptr->size;
alloctot += size;
}
else {
freenow = 'y';
size = mptr->size;
freetot += size;
}
if (verbose) {
printf("%3d: 0x%08lx %5d %c 0x%08lx 0x%08lx 0x%08lx ",
i,(ulong)(mptr+1),size,freenow,(ulong)mptr,
(ulong)(mptr->next),(ulong)(mptr->prev));
prascii((unsigned char *)(mptr+1),size > 16 ? 16 : size);
putchar('\n');
#ifdef MALLOC_DEBUG
if (freenow == 'n')
printf(" %s %d\n",mptr->fname,mptr->fline);
#endif
}
mptr = mptr->next;
}
if (verbose)
putchar('\n');
printf(" Malloc/realloc/free calls: %d/%d/%d\n",mcalls,rcalls,fcalls);
printf(" Malloc/free totals: %d/%d\n",mtot,ftot);
printf(" High-water level: %d\n",highwater);
printf(" Malloc failures: %d\n",mfails);
printf(" Bytes overhead: %d\n",i * MHDRSIZE);
printf(" Bytes currently allocated: %d\n",alloctot);
printf(" Bytes free on current heap: %d\n",freetot);
printf(" Bytes left in allocation pool: %d\n",GetMemoryLeft());
}
/* releaseExtendedHeap():
* If memory has been allocated through the extended heap established
* by the heap -x{start,size} command, this function will attempt
* to "undo" that. It can only be un-done if there is no currently active
* allocations in that range.
*
* This function is accessible by the application through monlib.
*/
int
releaseExtendedHeap(int verbose)
{
int i;
struct mhdr *mptr, *extbase;
extbase = (struct mhdr *)getExtHeapBase();
if (!extbase) {
if (verbose)
printf("Heap extension not set\n");
return(-1);
}
heapcheck(0,0);
mptr = heapbase;
for(i=0;mptr;i++) {
if (mptr->next == extbase) {
if (mptr->next->next == (struct mhdr *)0) {
mptr->next = (struct mhdr *)0;
unExtendHeap();
if (verbose)
printf("Heap extension cleared\n");
return(0);
}
else if (verbose)
printf("Extended heap space is in use.\n");
break;
}
mptr = mptr->next;
}
if (!mptr) { /* Heap was extended, but not used. */
unExtendHeap(); /* Remove the extension. */
if (verbose)
printf("Heap extension cleared.\n");
}
return(0);
}
char *HeapHelp[] = {
"Display heap statistics.",
"-[cf:m:qvX:x]",
#if INCLUDE_VERBOSEHELP
"Options:",
" -c clear high-water level and malloc/free totals",
" -f{ptr} free block @ 'ptr'",
" -m{size} malloc 'size' bytes",
" -q quiet runtime (don't print MALLOC ERROR msgs)",
" -v verbose (more detail)",
" -X{base,size}",
" extend heap by 'size' bytes starting at 'base'",
" -x clear heap extension",
#endif
0
};
int
Heap(int argc,char *argv[])
{
char *establish_extended_heap, buf[32];
int verbose, release_extended_heap, showheap, opt;
showheap = 1;
establish_extended_heap = (char *)0;
release_extended_heap = verbose = 0;
while((opt=getopt(argc,argv,"cf:m:qvX:x")) != -1) {
switch(opt) {
case 'c':
mcalls = fcalls = 0;
mtot = ftot = highwater = 0;
showheap = 0;
break;
case 'f':
free((char *)strtoul(optarg,0,0));
showheap = 0;
break;
case 'm':
shell_sprintf("MALLOC","0x%lx",
(ulong)_malloc(strtoul(optarg,0,0)));
if (verbose)
printf("%s\n",buf);
showheap = 0;
break;
case 'q':
showheap = 0;
mquiet = 1;
break;
case 'v':
verbose = 1;
break;
case 'X':
establish_extended_heap = optarg;
showheap = 0;
break;
case 'x':
release_extended_heap = 1;
showheap = 0;
break;
default:
return(CMD_PARAM_ERROR);
}
}
if (release_extended_heap)
releaseExtendedHeap(verbose);
if (establish_extended_heap) {
int size;
char *comma, *begin;
comma = strchr(establish_extended_heap,',');
if (!comma)
return(CMD_PARAM_ERROR);
*comma = 0;
begin = (char *)strtoul(establish_extended_heap,0,0);
size = (int)strtoul(comma+1,0,0);
if (extendHeap(begin,size) == -1) {
printf("Extended heap already exists @ 0x%lx\n",
(ulong)getExtHeapBase());
return(CMD_FAILURE);
}
}
if (!showheap)
return(CMD_SUCCESS);
if (optind == argc)
heapdump(verbose);
return(CMD_SUCCESS);
}
#else
char *
malloc(int size)
{
return(0);
}
void
free(char *buf)
{
}
char *
realloc(char *buf, int newsize, char *fname, int fline)
{
return(0);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -