📄 mprof.c
字号:
{ if ((nodes = (profilenode *) malloc(nodesize * sizeof(profilenode))) == NULL) { fprintf(stderr, "%s: Out of memory\n", progname); exit(EXIT_FAILURE); } for (i = 0; i < nodesize; i++) { getentry(&n, sizeof(unsigned long), 1, b); p = &nodes[n - 1]; getentry(&p->parent, sizeof(unsigned long), 1, b); getentry(&p->addr, sizeof(void *), 1, b); getentry(&p->symbol, sizeof(unsigned long), 1, b); getentry(&p->name, sizeof(unsigned long), 1, b); getentry(&p->data, sizeof(unsigned long), 1, b); __mp_treeinsert(&proftree, &p->node, (unsigned long) p->addr); cleardata(&p->tdata); p->flags = 0; } } /* Read the table containing the symbol addresses. */ getentry(&i, sizeof(size_t), 1, b); if (i > 0) { if ((addrs = (void **) malloc(i * sizeof(void *))) == NULL) { fprintf(stderr, "%s: Out of memory\n", progname); exit(EXIT_FAILURE); } getentry(addrs, sizeof(void *), i, b); } /* Read the string table containing the symbol names. */ getentry(&i, sizeof(size_t), 1, b); if (i > 0) { if ((symbols = (char *) malloc(i * sizeof(char))) == NULL) { fprintf(stderr, "%s: Out of memory\n", progname); exit(EXIT_FAILURE); } getentry(symbols, sizeof(char), i, 0); } getentry(s, sizeof(char), 4, 0); if (memcmp(s, MP_PROFMAGIC, 4) != 0) { fprintf(stderr, "%s: Invalid file format\n", progname); exit(EXIT_FAILURE); }}/* Count the number of decimal digits in a number. */staticunsigned charcountdigits(unsigned long n){ unsigned char d; for (d = 1; n /= 10; d++); return d;}/* Display a character a specified number of times. */staticvoidprintchar(char c, size_t n){ size_t i; for (i = 0; i < n; i++) fputc(c, stdout);}/* Display a set of profiling data. */staticvoidprintdata(size_t *d, size_t t){ size_t i; double n; for (i = 0; i < 4; i++) if ((d[i] == 0) || (t == 0)) fputs(" ", stdout); else { n = ((double) d[i] / (double) t) * 100.0; if (n <= 0.5) fputs(" .", stdout); else if (n >= 99.5) fputs(" %%", stdout); else fprintf(stdout, " %2.0f", n); }}/* Display the symbol associated with a particular call site. */staticvoidprintsymbol(FILE *f, profilenode *n){ ptrdiff_t o; if (n->name == 0) fprintf(f, MP_POINTER, n->addr); else { fputs(symbols + n->name, f); if (useaddresses && (n->symbol != 0) && ((o = (char *) n->addr - (char *) addrs[n->symbol - 1]) != 0)) fprintf(f, "%+ld", o); }}/* Add a new vertex to the allocation call graph. */staticvertex *addvertex(profilenode *n){ vertex *v; if ((v = (vertex *) malloc(sizeof(vertex))) == NULL) { fprintf(stderr, "%s: Out of memory\n", progname); exit(EXIT_FAILURE); } if (useaddresses || (n->symbol == 0)) __mp_treeinsert(&temptree, &v->node, (unsigned long) n->addr); else __mp_treeinsert(&temptree, &v->node, n->symbol); __mp_addnode(&graph, &v->gnode); v->pnode = n; v->index = 0; return v;}/* Add a new edge to the allocation call graph. */staticedge *addedge(graphnode *p, graphnode *c){ edge *e; if ((e = (edge *) malloc(sizeof(edge))) == NULL) { fprintf(stderr, "%s: Out of memory\n", progname); exit(EXIT_FAILURE); } __mp_addtail(&edgelist, &e->node); __mp_addedge(&graph, &e->gnode, p, c); cleardata(&e->data); e->flags = 0; return e;}/* Build the allocation call graph. */staticvoidbuildgraph(void){ profilenode *n, *p; vertex *u, *v; edge *e; graphedge *g; profiledata d; for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = (profilenode *) __mp_successor(&n->node)) if ((n->data != 0) && !(n->flags & 1)) { cleardata(&d); sumdata(&d, &data[n->data - 1]); p = (profilenode *) __mp_successor(&n->node); while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses && (p->symbol != 0) && (p->symbol == n->symbol)))) { if ((p->data != 0) && !(p->flags & 1) && comparestack(n, p, 1)) { sumdata(&d, &data[p->data - 1]); p->flags |= 1; } p = (profilenode *) __mp_successor(&p->node); } p = n; if (useaddresses || (p->symbol == 0)) u = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else u = (vertex *) __mp_search(temptree.root, p->symbol); if (u == NULL) u = addvertex(p); if ((g = __mp_findedge(&graph, &u->gnode, &graph.end)) == NULL) e = addedge(&u->gnode, &graph.end); else e = (edge *) ((char *) g - offsetof(edge, gnode)); sumdata(&e->data, &d); u->pnode->flags |= 2; for (v = u; p->parent != 0; u = v) { p = &nodes[p->parent - 1]; if (useaddresses || (p->symbol == 0)) v = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else v = (vertex *) __mp_search(temptree.root, p->symbol); if (v == NULL) v = addvertex(p); if ((g = __mp_findedge(&graph, &v->gnode, &u->gnode)) == NULL) e = addedge(&v->gnode, &u->gnode); else e = (edge *) ((char *) g - offsetof(edge, gnode)); /* Find out if we've been here before. If we have then we have * detected a cycle in the call graph and we should not * contribute anything to the current edge since we have done so * already. However, we mark the edge as being part of a cycle * since it is useful to know this later on. */ if (v->pnode->flags & 2) e->flags |= 2; else { sumdata(&e->data, &d); v->pnode->flags |= 2; } } if ((g = __mp_findedge(&graph, &graph.start, &v->gnode)) == NULL) e = addedge(&graph.start, &v->gnode); else e = (edge *) ((char *) g - offsetof(edge, gnode)); sumdata(&e->data, &d); /* Clear all of the flags from the current call stack that we used * to determine cycles in the call graph. */ p = n; do { if (useaddresses || (p->symbol == 0)) v = (vertex *) __mp_search(temptree.root, (unsigned long) p->addr); else v = (vertex *) __mp_search(temptree.root, p->symbol); v->pnode->flags &= ~2; if (p->parent != 0) p = &nodes[p->parent - 1]; else p = NULL; } while (p != NULL); } for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = (profilenode *) __mp_successor(&n->node)) n->flags = 0;}/* Delete the allocation call graph. */staticvoiddeletegraph(void){ vertex *n, *v; edge *e, *m; /* Remove the nodes from the graph and free up the memory that they * inhabit. This is done by traversing the tree rather than the graph * in order to avoid deleting nodes that result in other nodes being * inaccessible. */ for (v = (vertex *) __mp_minimum(temptree.root); v != NULL; v = n) { n = (vertex *) __mp_successor(&v->node); __mp_treeremove(&temptree, &v->node); __mp_removenode(&graph, &v->gnode); free(v); } /* Remove the edges from the graph. The graph is now empty following * the removal of the nodes in the previous loop, so we just need to * free the memory that each edge uses. */ for (e = (edge *) edgelist.head; m = (edge *) e->node.next; e = m) { __mp_remove(&edgelist, &e->node); free(e); }}/* Display the allocation bin table. */staticvoidbintable(void){ size_t i; unsigned long a, b, c, d; double e, f, g, h; int p; p = 0; printchar(' ', 32); fputs("ALLOCATION BINS\n\n", stdout); printchar(' ', 29); fprintf(stdout, "(number of bins: %lu)\n\n", binsize); printchar(' ', 21); fputs("allocated", stdout); printchar(' ', 26); fputs("unfreed\n", stdout); printchar(' ', 10); printchar('-', 32); fputs(" ", stdout); printchar('-', 32); fputs("\n size count % bytes % " "count % bytes %\n\n", stdout); for (i = 0; i < binsize; i++) if (acounts[i] != 0) { a = acounts[i]; b = a - dcounts[i]; if (i == binsize - 1) { c = atotals; d = c - dtotals; } else { c = a * (i + 1); d = b * (i + 1); } e = ((double) a / (double) acount) * 100.0; if (acount != dcount) f = ((double) b / (double) (acount - dcount)) * 100.0; else f = 0.0; g = ((double) c / (double) atotal) * 100.0; if (atotal != dtotal) h = ((double) d / (double) (atotal - dtotal)) * 100.0; else h = 0.0; fprintf(stdout, " %s %4lu %6lu %6.2f %8lu %6.2f " "%6lu %6.2f %8lu %6.2f\n", (i == binsize - 1) ? ">=" : " ", i + 1, a, e, c, g, b, f, d, h); p = 1; } if (p == 1) fputc('\n', stdout); fprintf(stdout, " total %6lu %8lu " "%6lu %8lu\n", acount, atotal, acount - dcount, atotal - dtotal);}/* Display the direct allocation table. */staticvoiddirecttable(void){ profiledata *d; profilenode *n, *p; treenode *t; profiledata m; size_t i; unsigned long a, b, c; double e, f; cleardata(&m); printchar(' ', 31); fputs("DIRECT ALLOCATIONS\n\n", stdout); printchar(' ', 20); fprintf(stdout, "(0 < s <= %lu < m <= %lu < l <= %lu < x)\n\n", sbound, mbound, lbound); if (showcounts) { printchar(' ', 9); fputs("allocated", stdout); printchar(' ', 21); fputs("unfreed\n", stdout); printchar('-', 27); fputs(" ", stdout); printchar('-', 27); fputs("\n count % s m l x " "count % s m l x bytes function\n\n", stdout); } else { printchar(' ', 10); fputs("allocated", stdout); printchar(' ', 23); fputs("unfreed\n", stdout); printchar('-', 29); fputs(" ", stdout); printchar('-', 29); fputs("\n bytes % s m l x " "bytes % s m l x count function\n\n", stdout); } for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL; n = p) { p = (profilenode *) __mp_successor(&n->node); if (n->data != 0) { d = &n->tdata; sumdata(d, &data[n->data - 1]); while ((p != NULL) && ((p->addr == n->addr) || (!useaddresses && (p->symbol != 0) && (p->symbol == n->symbol)))) { if (p->data != 0) sumdata(d, &data[p->data - 1]); p = (profilenode *) __mp_successor(&p->node); } a = 0; for (i = 0; i < 4; i++) if (showcounts) a += d->acount[i]; else a += d->atotal[i]; __mp_treeinsert(&temptree, &n->tnode, a); sumdata(&m, d); } } for (t = __mp_maximum(temptree.root); t != NULL; t = __mp_predecessor(t)) { n = (profilenode *) ((char *) t - offsetof(profilenode, tnode)); d = &n->tdata; a = t->key; b = c = 0; for (i = 0; i < 4; i++) { if (showcounts) { b += d->dcount[i]; c += d->atotal[i]; } else { b += d->dtotal[i]; c += d->acount[i]; } d->dcount[i] = d->acount[i] - d->dcount[i]; d->dtotal[i] = d->atotal[i] - d->dtotal[i]; } b = a - b; if (showcounts) { e = ((double) a / (double) acount) * 100.0; if (acount != dcount) f = ((double) b / (double) (acount - dcount)) * 100.0; else f = 0.0; fprintf(stdout, "%6lu %6.2f ", a, e); printdata(d->acount, acount); fprintf(stdout, " %6lu %6.2f ", b, f); printdata(d->dcount, acount - dcount); fprintf(stdout, " %8lu ", c); } else { e = ((double) a / (double) atotal) * 100.0; if (atotal != dtotal) f = ((double) b / (double) (atotal - dtotal)) * 100.0; else f = 0.0; fprintf(stdout, "%8lu %6.2f ", a, e); printdata(d->atotal, atotal); fprintf(stdout, " %8lu %6.2f ", b, f); printdata(d->dtotal, atotal - dtotal); fprintf(stdout, " %6lu ", c); } printsymbol(stdout, n); fputc('\n', stdout); cleardata(d); } for (i = 0; i < 4; i++) { m.dcount[i] = m.acount[i] - m.dcount[i]; m.dtotal[i] = m.atotal[i] - m.dtotal[i]; } if (temptree.size != 0) fputc('\n', stdout); if (showcounts) { fprintf(stdout, "%6lu ", acount); printdata(m.acount, acount); fprintf(stdout, " %6lu ", acount - dcount); printdata(m.dcount, acount - dcount); fprintf(stdout, " %8lu total\n", atotal); } else { fprintf(stdout, "%8lu ", atotal); printdata(m.atotal, atotal); fprintf(stdout, " %8lu ", atotal - dtotal); printdata(m.dtotal, atotal - dtotal); fprintf(stdout, " %6lu total\n", acount); } __mp_newtree(&temptree);}/* Display the memory leak table. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -