📄 info.c
字号:
h->cpeak = h->alloc.atree.size; if (h->peak < h->alloc.asize) h->peak = h->alloc.asize; } /* If we are returning NULL from a call to reallocf() then we must * also free the original allocation. */ if ((p == NULL) && (v->type == AT_REALLOCF)) __mp_freememory(h, n->block, v); } if ((h->flags & FLG_LOGREALLOCS) && (h->recur == 1)) __mp_diag("returns " MP_POINTER "\n\n", p); return p;}/* Free an existing block of memory. */MP_GLOBALvoid__mp_freememory(infohead *h, void *p, loginfo *v){ allocnode *n; allocanode *g; infonode *m; unsigned long t; int o; v->ltype = LT_FREE; v->variant.logfree.block = p; if (h->flags & FLG_LOGFREES) __mp_log(h, v); if (p == NULL) { if (h->flags & FLG_CHECKFREES) { __mp_log(h, v); __mp_warn(ET_FRENUL, v->type, v->file, v->line, NULL); __mp_diag("\n"); } return; } if (n = __mp_findfreed(&h->alloc, p)) { /* This block of memory has already been freed but has not been * returned to the free tree. */ m = (infonode *) n->info; __mp_log(h, v); __mp_error(ET_PRVFRD, v->type, v->file, v->line, NULL, p, __mp_functionnames[m->data.type]); __mp_printalloc(&h->syms, n); __mp_diag("\n"); } else if (((n = __mp_findalloc(&h->alloc, p)) == NULL) || ((m = (infonode *) n->info) == NULL)) { /* We know nothing about this block of memory. */ __mp_log(h, v); __mp_error(ET_NOTALL, v->type, v->file, v->line, NULL, p); __mp_diag("\n"); } else if (p != n->block) { /* The address of the block passed in does not match the start * address of the block we know about. */ __mp_log(h, v); __mp_error(ET_MISMAT, v->type, v->file, v->line, NULL, p, n->block); __mp_printalloc(&h->syms, n); __mp_diag("\n"); } else if ((((m->data.type == AT_ALLOCA) || (m->data.type == AT_STRDUPA) || (m->data.type == AT_STRNDUPA)) && (v->type != AT_ALLOCA) && (v->type != AT_DEALLOCA)) || ((m->data.type != AT_ALLOCA) && (m->data.type != AT_STRDUPA) && (m->data.type != AT_STRNDUPA) && ((v->type == AT_ALLOCA) || (v->type == AT_DEALLOCA))) || ((m->data.type == AT_NEW) && (v->type != AT_DELETE)) || ((m->data.type != AT_NEW) && (v->type == AT_DELETE)) || ((m->data.type == AT_NEWVEC) && (v->type != AT_DELETEVEC)) || ((m->data.type != AT_NEWVEC) && (v->type == AT_DELETEVEC))) { /* The function used to allocate the block is incompatible with * the function used to free the block. */ __mp_log(h, v); __mp_error(ET_INCOMP, v->type, v->file, v->line, NULL, p, __mp_functionnames[m->data.type]); __mp_printalloc(&h->syms, n); __mp_diag("\n"); } else if (m->data.flags & FLG_MARKED) { /* An attempt was made to free a marked memory allocation. */ __mp_log(h, v); __mp_error(ET_FREMRK, v->type, v->file, v->line, NULL, p); __mp_printalloc(&h->syms, n); __mp_diag("\n"); } else {#if MP_THREADS_SUPPORT t = __mp_threadid();#else /* MP_THREADS_SUPPORT */ t = 0;#endif /* MP_THREADS_SUPPORT */ if ((h->flags & FLG_LOGFREES) && (h->recur == 1)) { __mp_printalloc(&h->syms, n); __mp_diag("\n"); } if (m->data.alloc == h->fstop) { /* Abort at the specified allocation index. */ __mp_printsummary(h); __mp_diag("\n"); __mp_diag("stopping at freeing of allocation %lu\n", h->fstop); __mp_trap(); } if (!(h->flags & FLG_NOPROTECT)) __mp_protectinfo(h, MA_READWRITE); if (h->ltable.tracing) leaktabentry(h, m, n->size, 1); if (m->data.flags & FLG_PROFILED) __mp_profilefree(&h->prof, n->size, m, !(h->flags & FLG_NOPROTECT)); if (m->data.flags & FLG_TRACED) __mp_tracefree(&h->trace, m->data.alloc, t, v->func, v->file, v->line); __mp_freeaddrs(&h->addr, m->data.stack); if (h->alloc.flags & FLG_NOFREE) { /* Fill in the details of the allocation information node but only * if we are keeping the freed block. */ m->data.type = v->type;#if MP_THREADS_SUPPORT m->data.thread = t;#endif /* MP_THREADS_SUPPORT */ m->data.event = h->event; m->data.func = v->func; m->data.file = v->file; m->data.line = v->line; m->data.stack = __mp_getaddrs(&h->addr, v->stack); m->data.flags |= FLG_FREED; } else { __mp_freeslot(&h->table, m); m = NULL; } if ((v->type == AT_ALLOCA) || (v->type == AT_DEALLOCA)) { /* Search the alloca allocation stack for the allocanode to free. * We need to do this instead of just blindly removing the top of * the stack since it is possible for the user to manually free an * allocation that was created by one of the alloca() family of * functions through the use of the dealloca() function. */ o = 0; for (g = (allocanode *) h->astack.head; g->node.next != NULL; g = (allocanode *) g->node.next) if (g->block == p) { o = 1; break; } if (o == 1) { __mp_remove(&h->astack, &g->node); __mp_freeslot(&h->atable, g); } }#if MP_INUSE_SUPPORT _Inuse_free(p);#endif /* MP_INUSE_SUPPORT */ __mp_freealloc(&h->alloc, n, m); if ((h->recur == 1) && !(h->flags & FLG_NOPROTECT)) __mp_protectinfo(h, MA_READONLY); }}/* Set a block of memory to contain a specific byte. */MP_GLOBALvoid__mp_setmemory(infohead *h, void *p, size_t l, unsigned char c, loginfo *v){ v->ltype = LT_SET; v->variant.logmemset.block = p; v->variant.logmemset.size = l; v->variant.logmemset.byte = c; if (h->flags & FLG_LOGMEMORY) __mp_log(h, v); /* If the pointer is not NULL and does not overflow any memory blocks then * proceed to set the memory. */ if (__mp_checkrange(h, p, l, v)) { __mp_memset(p, c, l); h->stotal += l; }}/* Copy a block of memory from one address to another. */MP_GLOBALvoid *__mp_copymemory(infohead *h, void *p, void *q, size_t l, unsigned char c, loginfo *v){ void *r; v->ltype = LT_COPY; v->variant.logmemcopy.srcblock = p; v->variant.logmemcopy.dstblock = q; v->variant.logmemcopy.size = l; v->variant.logmemcopy.byte = c; if (h->flags & FLG_LOGMEMORY) __mp_log(h, v); /* We must ensure that the memory to be copied does not overlap when * memcpy() or memccpy() are called. This does not matter when calling * __mp_memcopy() but it will matter when calling the normal system * functions, in which case memmove() should be used instead. */ if (((v->type == AT_MEMCPY) || (v->type == AT_MEMCCPY)) && (l > 0) && (((p < q) && ((char *) p + l > (char *) q)) || ((q < p) && ((char *) q + l > (char *) p)))) { __mp_log(h, v); __mp_warn(ET_RNGOVL, v->type, v->file, v->line, NULL, p, (char *) p + l - 1, q, (char *) q + l - 1); __mp_diag("\n"); } /* If the pointers are not NULL and do not overflow any memory blocks then * proceed to copy the memory. */ if (__mp_checkrange(h, p, l, v) && __mp_checkrange(h, q, l, v)) { if (v->type == AT_MEMCCPY) { if (r = __mp_memfind(p, l, &c, 1)) l = (size_t) ((char *) r - (char *) p) + 1; __mp_memcopy(q, p, l); if (r != NULL) q = (char *) q + l; else q = NULL; } else __mp_memcopy(q, p, l); h->ctotal += l; } if ((h->flags & FLG_LOGMEMORY) && (h->recur == 1)) __mp_diag("returns " MP_POINTER "\n\n", q); return q;}/* Attempt to locate the position of one block of memory in another block. */MP_GLOBALvoid *__mp_locatememory(infohead *h, void *p, size_t l, void *q, size_t m, loginfo *v){ void *r; r = NULL; v->ltype = LT_LOCATE; v->variant.logmemlocate.block = p; v->variant.logmemlocate.size = l; v->variant.logmemlocate.patblock = q; v->variant.logmemlocate.patsize = m; if (h->flags & FLG_LOGMEMORY) __mp_log(h, v); /* If the pointers are not NULL and do not overflow any memory blocks then * proceed to start the search. */ if (__mp_checkrange(h, p, l, v) && __mp_checkrange(h, q, m, v)) { r = __mp_memfind(p, l, q, m); h->ltotal += m; } if ((h->flags & FLG_LOGMEMORY) && (h->recur == 1)) __mp_diag("returns " MP_POINTER "\n\n", r); return r;}/* Compare two blocks of memory. */MP_GLOBALint__mp_comparememory(infohead *h, void *p, void *q, size_t l, loginfo *v){ void *r; int c; c = 0; v->ltype = LT_COMPARE; v->variant.logmemcompare.block1 = p; v->variant.logmemcompare.block2 = q; v->variant.logmemcompare.size = l; if (h->flags & FLG_LOGMEMORY) __mp_log(h, v); /* If the pointers are not NULL and do not overflow any memory blocks then * proceed to compare the memory. */ if (__mp_checkrange(h, p, l, v) && __mp_checkrange(h, q, l, v)) { h->dtotal += l; if (r = __mp_memcompare(p, q, l)) { l = (char *) r - (char *) p; c = (int) ((unsigned char *) p)[l] - (int) ((unsigned char *) q)[l]; } } if ((h->flags & FLG_LOGMEMORY) && (h->recur == 1)) __mp_diag("returns %d\n\n", c); return c;}/* Protect the internal memory blocks used by the mpatrol library * with the supplied access permission. */MP_GLOBALint__mp_protectinfo(infohead *h, memaccess a){ allocanode *m; infonode *n; /* The library already knows what its protection status is so we don't * need to do anything if the request has already been done. */ if (a == h->prot) return 1; h->prot = a; for (n = (infonode *) h->list.head; n->index.node.next != NULL; n = (infonode *) n->index.node.next) if (!__mp_memprotect(&h->alloc.heap.memory, n->index.block, n->index.size, a)) return 0; for (m = (allocanode *) h->alist.head; m->node.next != NULL; m = (allocanode *) m->node.next) if (!__mp_memprotect(&h->alloc.heap.memory, m->block, m->data.size, a)) return 0; if (!__mp_protectaddrs(&h->addr, a) || !__mp_protectleaktab(&h->ltable, a) || !__mp_protectprofile(&h->prof, a)) return 0; return __mp_protectalloc(&h->alloc, a);}/* Check the validity of all memory blocks that have been filled with * a predefined pattern.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -