⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mprof.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
staticvoidleaktable(void){    profiledata *d;    profilenode *n, *p;    treenode *t;    size_t i;    unsigned long a, b, j, k;    double e, f, g;    printchar(' ', 34);    fputs("MEMORY LEAKS\n\n", stdout);    printchar(' ', 28);    fprintf(stdout, "(maximum stack depth: %lu)\n\n", maxstack);    printchar(' ', 16);    fputs("unfreed", stdout);    printchar(' ', 22);    fputs("allocated\n", stdout);    printchar('-', 40);    fputs("  ", stdout);    printchar('-', 16);    if (showcounts)        fputs("\n     %   count       %     bytes       %   "              "count     bytes  function\n\n", stdout);    else        fputs("\n     %     bytes       %   count       %     "              "bytes   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) && !n->flags)        {            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) && !p->flags && comparestack(n, p, 0))                {                    sumdata(d, &data[p->data - 1]);                    p->flags = 1;                }                p = (profilenode *) __mp_successor(&p->node);            }            p = (profilenode *) __mp_successor(&n->node);            a = 0;            for (i = 0; i < 4; i++)                if (showcounts)                    a += d->acount[i] - d->dcount[i];                else                    a += d->atotal[i] - d->dtotal[i];            if (a > 0)                __mp_treeinsert(&temptree, &n->tnode, a);        }    }    for (n = (profilenode *) __mp_minimum(proftree.root); n != NULL;         n = (profilenode *) __mp_successor(&n->node))        n->flags = 0;    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 = j = k = 0;        for (i = 0; i < 4; i++)            if (showcounts)            {                b += d->dtotal[i];                j += d->acount[i];                k += d->atotal[i];            }            else            {                b += d->dcount[i];                j += d->atotal[i];                k += d->acount[i];            }        b = k - b;        e = ((double) a / (double) j) * 100.0;        f = ((double) b / (double) k) * 100.0;        if (showcounts)        {            g = ((double) a / (double) (acount - dcount)) * 100.0;            fprintf(stdout, "%6.2f  %6lu  %6.2f  %8lu  %6.2f  %6lu  %8lu  ",                    g, a, e, b, f, j, k);        }        else        {            g = ((double) a / (double) (atotal - dtotal)) * 100.0;            fprintf(stdout, "%6.2f  %8lu  %6.2f  %6lu  %6.2f  %8lu  %6lu  ",                    g, a, e, b, f, j, k);        }        printsymbol(stdout, n);        fputc('\n', stdout);        p = n;        for (i = 1; (maxstack == 0) || (i < maxstack); i++)        {            if (p->parent == 0)                break;            p = &nodes[p->parent - 1];            printchar(' ', 60);            printsymbol(stdout, p);            fputc('\n', stdout);        }        cleardata(d);    }    if (acount != 0)        e = ((double) (acount - dcount) / (double) acount) * 100.0;    else        e = 0.0;    if (atotal != 0)        f = ((double) (atotal - dtotal) / (double) atotal) * 100.0;    else        f = 0.0;    if (temptree.size != 0)        fputc('\n', stdout);    if (showcounts)        fprintf(stdout, "        %6lu  %6.2f  %8lu  %6.2f  %6lu  %8lu  total\n",                acount - dcount, e, atotal - dtotal, f, acount, atotal);    else        fprintf(stdout, "        %8lu  %6.2f  %6lu  %6.2f  %8lu  %6lu  total\n",                atotal - dtotal, f, acount - dcount, e, atotal, acount);    __mp_newtree(&temptree);}/* Display the allocation call graph. */staticvoidcallgraph(void){    size_t d[4];    listnode *l;    vertex *u, *v;    edge *e;    graphedge *g;    size_t i, s, t;    i = 1;    printchar(' ', 29);    fputs("ALLOCATION CALL GRAPH\n\n", stdout);    printchar(' ', 28);    fprintf(stdout, "(number of vertices: %lu)\n\n", temptree.size);    if (showcounts)    {        printchar(' ', 10);        fputs("allocated", stdout);        printchar(' ', 13);        fputs("unfreed\n", stdout);        printchar(' ', 5);        printchar('-', 19);        fputs("  ", stdout);        printchar('-', 19);        fputs("\nindex count   s  m  l  x   count   s  m  l  x  function\n",              stdout);    }    else    {        printchar(' ', 11);        fputs("allocated", stdout);        printchar(' ', 15);        fputs("unfreed\n", stdout);        printchar(' ', 5);        printchar('-', 21);        fputs("  ", stdout);        printchar('-', 21);        fputs("\nindex   bytes   s  m  l  x     bytes   s  m  l  x  function\n",              stdout);    }    /* Compute the index for each vertex in the graph.  This is currently     * done after the graph has been completely constructed so that the     * ordering can be done by code address.  It has to be done before we     * start displaying the graph since each vertex will contain forward     * references to its parents and children.     */    for (v = (vertex *) __mp_minimum(temptree.root); v != NULL;         v = (vertex *) __mp_successor(&v->node))        v->index = i++;    for (v = (vertex *) __mp_minimum(temptree.root); v != NULL;         v = (vertex *) __mp_successor(&v->node))    {        if (showcounts)            printchar('-', 45);        else            printchar('-', 49);        fputc('\n', stdout);        /* Calculate the details of the parents.         */        for (l = v->gnode.parents.head; l->next != NULL; l = l->next)        {            /* The following three lines are a bit excessive and result from             * using class-based programming in C.  These conversions would be             * automatically calculated by the compiler if we were using C++             * classes.             */            g = (graphedge *) ((char *) l - offsetof(graphedge, pnode));            e = (edge *) ((char *) g - offsetof(edge, gnode));            u = (vertex *) ((char *) e->gnode.parent - offsetof(vertex, gnode));            if (&u->gnode != &graph.start)            {                for (i = s = t = 0; i < 4; i++)                {                    if (showcounts)                    {                        t += e->data.acount[i];                        d[i] = e->data.acount[i] - e->data.dcount[i];                    }                    else                    {                        t += e->data.atotal[i];                        d[i] = e->data.atotal[i] - e->data.dtotal[i];                    }                    s += d[i];                }                if (e->flags & 2)                    fputs(" (*) ", stdout);                else                    printchar(' ', 5);                if (showcounts)                {                    fprintf(stdout, "%6lu ", t);                    printdata(e->data.acount, t);                    fprintf(stdout, "  %6lu ", s);                }                else                {                    fprintf(stdout, "%8lu ", t);                    printdata(e->data.atotal, t);                    fprintf(stdout, "  %8lu ", s);                }                printdata(d, s);                printchar(' ', 6);                printsymbol(stdout, u->pnode);                fprintf(stdout, " [%lu]\n", u->index);            }        }        fprintf(stdout, "[%lu] ", v->index);        if (showcounts)            printchar(' ', 44 - countdigits(v->index));        else            printchar(' ', 48 - countdigits(v->index));        printsymbol(stdout, v->pnode);        fprintf(stdout, " [%lu]\n", v->index);        /* Calculate the details of the children.         */        for (l = v->gnode.children.head; l->next != NULL; l = l->next)        {            /* The following three lines are a bit excessive and result from             * using class-based programming in C.  These conversions would be             * automatically calculated by the compiler if we were using C++             * classes.             */            g = (graphedge *) ((char *) l - offsetof(graphedge, cnode));            e = (edge *) ((char *) g - offsetof(edge, gnode));            u = (vertex *) ((char *) e->gnode.child - offsetof(vertex, gnode));            if (&u->gnode != &graph.end)            {                for (i = s = t = 0; i < 4; i++)                {                    if (showcounts)                    {                        t += e->data.acount[i];                        d[i] = e->data.acount[i] - e->data.dcount[i];                    }                    else                    {                        t += e->data.atotal[i];                        d[i] = e->data.atotal[i] - e->data.dtotal[i];                    }                    s += d[i];                }                if (e->flags & 2)                    fputs(" (*) ", stdout);                else                    printchar(' ', 5);                if (showcounts)                {                    fprintf(stdout, "%6lu ", t);                    printdata(e->data.acount, t);                    fprintf(stdout, "  %6lu ", s);                }                else                {                    fprintf(stdout, "%8lu ", t);                    printdata(e->data.atotal, t);                    fprintf(stdout, "  %8lu ", s);                }                printdata(d, s);                printchar(' ', 6);                printsymbol(stdout, u->pnode);                fprintf(stdout, " [%lu]\n", u->index);            }        }    }}/* Write out the graph specification file in dot format. */staticvoidwritegraph(profilenode *p, graphnode *n){    listnode *l;    vertex *v;    edge *e;    graphedge *g;    size_t i, t;    for (l = n->children.head; l->next != NULL; l = l->next)    {        /* The following three lines are a bit excessive and result from         * using class-based programming in C.  These conversions would be         * automatically calculated by the compiler if we were using C++         * classes.         */        g = (graphedge *) ((char *) l - offsetof(graphedge, cnode));        e = (edge *) ((char *) g - offsetof(edge, gnode));        v = (vertex *) ((char *) e->gnode.child - offsetof(vertex, gnode));        if (!(e->flags & 1))        {            e->flags |= 1;            for (i = t = 0; i < 4; i++)                if (showcounts)                {                    t += e->data.acount[i];                    if (showleaks)                        t -= e->data.dcount[i];                }                else                {                    t += e->data.atotal[i];                    if (showleaks)                        t -= e->data.dtotal[i];                }            if ((t > 0) || !showleaks)            {                fputs("    \"", graphfile);                if (p == NULL)                    fputs("START", graphfile);                else                    printsymbol(graphfile, p);                fputs("\" -> \"", graphfile);                if (&v->gnode == &graph.end)                    fputs("ALLOC", graphfile);                else                    printsymbol(graphfile, v->pnode);                fprintf(graphfile, "\" [label = \"%lu\"", t);                if (e->flags & 2)                    fputs(", style = dotted", graphfile);                fputs("];\n", graphfile);            }            writegraph(v->pnode, &v->gnode);        }    }    if (p == NULL)        for (e = (edge *) edgelist.head; e->node.next != NULL;             e = (edge *) e->node.next)            e->flags &= ~1;}/* Read the profiling output file and display all specified information. */intmain(int argc, char **argv){    char b[256];    char *f, *g;    int c, e, h, r, v;    g = NULL;    e = h = v = 0;    r = EXIT_SUCCESS;    maxstack = 1;    progname = __mp_basename(argv[0]);    while ((c = __mp_getopt(argc, argv, __mp_shortopts(b, options_table),             options_table)) != EOF)        switch (c)        {          case OF_ADDRESSES:            useaddresses = 1;            break;          case OF_CALLGRAPH:            showgraph = 1;            break;          case OF_COUNTS:            showcounts = 1;            break;          case OF_GRAPHFILE:            g = __mp_optarg;            break;          case OF_HELP:            h = 1;            break;          case OF_LEAKS:            showleaks = 1;            break;          case OF_STACKDEPTH:            if (!__mp_getnum(progname, __mp_optarg, (long *) &maxstack, 1))                e = 1;            break;          case OF_VERSION:            v = 1;            break;          default:            e = 1;            break;        }    argc -= __mp_optindex;    argv += __mp_optindex;    if (v == 1)    {        fprintf(stdout, "%s %s\n%s %s\n\n", progname, PROGVERSION,                __mp_copyright, __mp_author);        fputs("This is free software, and you are welcome to redistribute it "              "under certain\n", stdout);        fputs("conditions; see the GNU Library General Public License for "              "details.\n\n", stdout);        fputs("For the latest mpatrol release and documentation,\n", stdout);        fprintf(stdout, "visit %s.\n\n", __mp_homepage);    }    if (argc > 1)        e = 1;    if ((e == 1) || (h == 1))    {        fprintf(stdout, "Usage: %s [options] [file]\n\n", progname);        if (h == 0)            fprintf(stdout, "Type `%s --help' for a complete list of "                    "options.\n", progname);        else            __mp_showopts(options_table);        if (e == 1)            exit(EXIT_FAILURE);        exit(EXIT_SUCCESS);    }    if (argc == 1)        f = argv[0];    else        f = MP_PROFFILE;    acount = dcount = 0;    atotal = dtotal = 0;    acounts = dcounts = NULL;    atotals = dtotals = 0;    binsize = 0;    data = NULL;    datasize = 0;    nodes = NULL;    nodesize = 0;    addrs = NULL;    symbols = NULL;    sbound = mbound = lbound = 0;    __mp_newtree(&proftree);    __mp_newtree(&temptree);    __mp_newlist(&edgelist);    __mp_newgraph(&graph);    if (strcmp(f, "-") == 0)        proffile = stdin;    else if ((proffile = fopen(f, "rb")) == NULL)    {        fprintf(stderr, "%s: Cannot open file `%s'\n", progname, f);        exit(EXIT_FAILURE);    }    readfile();    fclose(proffile);    bintable();    fputs("\n\n", stdout);    directtable();    fputs("\n\n", stdout);    leaktable();    /* The reason that the allocation call graph is not used for the direct     * allocation and memory leak tables is that the code to build and display     * the allocation call graph was added much later.  Rather than convert     * these tables to use the new call graph, I decided to keep the code that     * already worked and only use the call graph for any new tables.     */    buildgraph();    if (showgraph)    {        fputs("\n\n", stdout);        callgraph();    }    if (g != NULL)    {        if (strcmp(g, "stdout") == 0)            graphfile = stdout;        else if (strcmp(g, "stderr") == 0)            graphfile = stderr;        else if ((graphfile = fopen(g, "w")) == NULL)        {            fprintf(stderr, "%s: Cannot open file `%s'\n", progname, g);            r = EXIT_FAILURE;        }        if (r == EXIT_SUCCESS)        {            fprintf(graphfile, "/* produced by %s %s from %s */\n\n", progname,                    PROGVERSION, f);            if (showleaks)                fputs("digraph \"memory leak call graph\"\n{\n", graphfile);            else                fputs("digraph \"allocation call graph\"\n{\n", graphfile);            writegraph(NULL, &graph.start);            fputs("}\n", graphfile);            if ((graphfile != stdout) && (graphfile != stderr))                fclose(graphfile);        }    }    deletegraph();    if (acounts != NULL)        free(acounts);    if (dcounts != NULL)        free(dcounts);    if (data != NULL)        free(data);    if (nodes != NULL)        free(nodes);    if (addrs != NULL)        free(addrs);    if (symbols != NULL)        free(symbols);    return r;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -