📄 info.c
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * Allocation information. The functions in this module deal primarily with * the secondary information associated with memory allocations. */#include "info.h"#include "diag.h"#if MP_THREADS_SUPPORT#include "mutex.h"#endif /* MP_THREADS_SUPPORT */#include "utils.h"#include <stdlib.h>#include <errno.h>#if MP_IDENT_SUPPORT#ident "$Id: info.c,v 1.101 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *info_id = "$Id: info.c,v 1.101 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */MP_API void __mp_trap(void);#if MP_INUSE_SUPPORTvoid _Inuse_malloc(void *, unsigned long);void _Inuse_realloc(void *, void *, unsigned long);void _Inuse_free(void *);#endif /* MP_INUSE_SUPPORT *//* Initialise the fields of an infohead so that the mpatrol library * is ready to perform dynamic memory allocations. */MP_GLOBALvoid__mp_newinfo(infohead *h){ struct { char x; allocanode y; } w; struct { char x; infonode y; } z; long n; /* The signal table is initialised before this function is called * because we have already entered the library at this point. The * same goes for the recur field. */ __mp_newallocs(&h->alloc, 0, MP_OVERFLOW, MP_OVERBYTE, MP_ALLOCBYTE, MP_FREEBYTE, 0); __mp_newaddrs(&h->addr, &h->alloc.heap); __mp_newsymbols(&h->syms, &h->alloc.heap, h); __mp_newleaktab(&h->ltable, &h->alloc.heap); __mp_newprofile(&h->prof, &h->alloc.heap, &h->syms); __mp_newtrace(&h->trace, &h->alloc.heap.memory); /* Determine the minimum alignment for an allocation information node * on this system and force the alignment to be a power of two. This * information is used when initialising the slot table. Likewise for * the slot table of allocanodes. */ n = (char *) &z.y - &z.x; __mp_newslots(&h->table, sizeof(infonode), __mp_poweroftwo(n)); n = (char *) &w.y - &w.x; __mp_newslots(&h->atable, sizeof(allocanode), __mp_poweroftwo(n)); __mp_newlist(&h->list); __mp_newlist(&h->alist); __mp_newlist(&h->astack); /* Initialise the settings to their default values. */ h->size = h->event = h->count = h->cpeak = h->peak = h->limit = 0; h->astop = h->rstop = h->fstop = h->uabort = 0; h->lrange = h->urange = 0; h->check = 1; h->mcount = h->mtotal = 0; h->dtotal = h->ltotal = h->ctotal = h->stotal = 0; h->ffreq = h->fseed = 0; h->prologue = NULL; h->epilogue = NULL; h->nomemory = NULL; h->initcount = h->finicount = 0; h->log = __mp_logfile(&h->alloc.heap.memory, NULL); h->delpos = 0;#if MP_PROTECT_SUPPORT h->flags = 0;#else /* MP_PROTECT_SUPPORT */ /* If the system does not support memory protection then we just set the * NOPROTECT flag here, which saves us calling a function which does nothing * each time we want to protect the library's internal structures. */ h->flags = FLG_NOPROTECT;#endif /* MP_PROTECT_SUPPORT */ h->pid = __mp_processid(); h->prot = MA_READWRITE; /* Now that the infohead has valid fields we can now set the initialised * flag. This means that the library can now recursively call malloc() * or another memory allocation function without any problems. It just * means that there will not be a log entry at that point, but generally * we don't need one as the user will only want to see their memory * allocations. */ h->init = 1; h->fini = 0;}/* Free up all memory used by the infohead. */MP_GLOBALvoid__mp_deleteinfo(infohead *h){ h->log = NULL; __mp_deleteprofile(&h->prof); __mp_deleteleaktab(&h->ltable); __mp_deletesymbols(&h->syms); __mp_deleteaddrs(&h->addr); __mp_deleteallocs(&h->alloc); h->table.free = NULL; h->table.size = 0; h->atable.free = NULL; h->atable.size = 0; __mp_newlist(&h->list); __mp_newlist(&h->alist); __mp_newlist(&h->astack); h->size = h->event = h->count = h->cpeak = h->peak = 0; h->mcount = h->mtotal = 0; h->dtotal = h->ltotal = h->ctotal = h->stotal = 0; h->initcount = h->finicount = 0; h->delpos = 0;}/* Register an initialisation function to be called when the library is * initialised. */MP_GLOBALint__mp_atinit(infohead *h, void (*f)(void)){ int r; if (h->initcount == MP_MAXINITS) r = 0; else { h->inits[h->initcount++] = f; r = 1; } return r;}/* Register a finalisation function to be called when the library is * terminated. */MP_GLOBALint__mp_atfini(infohead *h, void (*f)(void)){ int r; if (h->finicount == MP_MAXFINIS) r = 0; else { h->finis[h->finicount++] = f; r = 1; } return r;}/* Allocate a new allocation information node. */staticinfonode *getinfonode(infohead *h){ infonode *n; heapnode *p; /* If we have no more allocation information node slots left then we * must allocate some more memory for them. An extra MP_ALLOCFACTOR * pages of memory should suffice. */ if ((n = (infonode *) __mp_getslot(&h->table)) == NULL) { if ((p = __mp_heapalloc(&h->alloc.heap, h->alloc.heap.memory.page * MP_ALLOCFACTOR, h->table.entalign, 1)) == NULL) return NULL; __mp_initslots(&h->table, p->block, p->size); n = (infonode *) __mp_getslot(&h->table); __mp_addtail(&h->list, &n->index.node); n->index.block = p->block; n->index.size = p->size; h->size += p->size; n = (infonode *) __mp_getslot(&h->table); } return n;}/* Allocate a new allocanode. */staticallocanode *getallocanode(infohead *h){ allocanode *n; heapnode *p; /* If we have no more allocanode slots left then we must allocate some more * memory for them. An extra MP_ALLOCFACTOR pages of memory should suffice. */ if ((n = (allocanode *) __mp_getslot(&h->atable)) == NULL) { if ((p = __mp_heapalloc(&h->alloc.heap, h->alloc.heap.memory.page * MP_ALLOCFACTOR, h->atable.entalign, 1)) == NULL) return NULL; __mp_initslots(&h->atable, p->block, p->size); n = (allocanode *) __mp_getslot(&h->atable); __mp_addtail(&h->alist, &n->node); n->block = p->block; n->data.size = p->size; h->size += p->size; n = (allocanode *) __mp_getslot(&h->atable); } return n;}/* Add an entry to the leak table. */staticvoidleaktabentry(infohead *h, infonode *m, size_t l, int f){ addrnode *a; symnode *s; char *t; unsigned long u; t = NULL; u = 0; if ((m->data.file != NULL) && (m->data.line != 0)) { t = m->data.file; u = m->data.line; } else if (m->data.func != NULL) t = m->data.func; else if (a = m->data.stack) { if ((a->data.name == NULL) && (s = __mp_findsymbol(&h->syms, a->data.addr))) a->data.name = s->data.name; if (a->data.name != NULL) t = a->data.name; else u = (unsigned long) a->data.addr; } if (f == 0) __mp_allocentry(&h->ltable, t, u, l); else __mp_freeentry(&h->ltable, t, u, l);}/* Allocate a new block of memory of a specified size and alignment. */MP_GLOBALvoid *__mp_getmemory(infohead *h, size_t l, size_t a, loginfo *v){ allocnode *n; allocanode *g; infonode *m; void *p; unsigned long c, t; p = NULL; h->count++; c = h->count; v->ltype = LT_ALLOC; v->variant.logalloc.size = l; v->variant.logalloc.align = a; if (h->flags & FLG_LOGALLOCS) __mp_log(h, v); if ((c == h->astop) && (h->rstop == 0)) { /* Abort at the specified allocation index. */ __mp_printsummary(h); __mp_diag("\n"); __mp_diag("stopping at allocation %lu\n", h->astop); __mp_trap(); } if ((h->flags & FLG_CHECKALLOCS) && (l == 0)) { __mp_log(h, v); __mp_warn(ET_ALLZER, v->type, v->file, v->line, NULL); __mp_diag("\n"); } if (v->type == AT_MEMALIGN) { /* Check that the specified alignment is valid. This is only * performed for memalign() so that we can report any problems * in the log file. All other cases are checked silently. */ if (a == 0) { if (h->flags & FLG_CHECKALLOCS) { __mp_log(h, v); __mp_warn(ET_ZERALN, v->type, v->file, v->line, NULL); __mp_diag("\n"); } a = h->alloc.heap.memory.align; } else if (!__mp_ispoweroftwo(a)) { if (h->flags & FLG_CHECKALLOCS) { __mp_log(h, v); __mp_warn(ET_BADALN, v->type, v->file, v->line, NULL, a); __mp_diag("\n"); } a = __mp_poweroftwo(a); } else if (a > h->alloc.heap.memory.page) { if (h->flags & FLG_CHECKALLOCS) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -