Ejemplo n.º 1
0
MP_GLOBAL
void
__mp_heapfree(heaphead *h, heapnode *n)
{
    h->dsize -= n->size;
    __mp_memfree(&h->memory, n->block, n->size);
    __mp_treeremove(&h->dtree, &n->node);
    __mp_freeslot(&h->table, n);
}
Ejemplo n.º 2
0
static
allocnode *
mergenode(allochead *h, allocnode *n)
{
    allocnode *l, *r;

    /* See if the left node is free and borders on this node.
     */
    l = (allocnode *) n->lnode.prev;
    if ((l->lnode.prev == NULL) || (l->info != NULL) ||
        ((char *) l->block + l->size < (char *) n->block))
        l = NULL;
    /* See if the right node is free and borders on this node.
     */
    r = (allocnode *) n->lnode.next;
    if ((r->lnode.next == NULL) || (r->info != NULL) ||
        ((char *) n->block + n->size < (char *) r->block))
        r = NULL;
    /* If either or both of the left or right node is suitable for
     * merging then perform the merge.
     */
    if ((l != NULL) || (r != NULL))
    {
        __mp_treeremove(&h->ftree, &n->tnode);
        if (l != NULL)
        {
            __mp_remove(&h->list, &l->lnode);
            __mp_treeremove(&h->ftree, &l->tnode);
            n->block = l->block;
            n->size += l->size;
            __mp_freeslot(&h->table, l);
        }
        if (r != NULL)
        {
            __mp_remove(&h->list, &r->lnode);
            __mp_treeremove(&h->ftree, &r->tnode);
            n->size += r->size;
            __mp_freeslot(&h->table, r);
        }
        __mp_treeinsert(&h->ftree, &n->tnode, n->size);
    }
    return n;
}
Ejemplo n.º 3
0
MP_GLOBAL
heapnode *
__mp_heapalloc(heaphead *h, size_t l, size_t a, int i)
{
    heapnode *n;
    void *p;
    size_t s;

    /* If we have no more heap node slots left then we must allocate
     * some more memory for them.  An extra MP_ALLOCFACTOR pages of memory
     * should suffice.
     */
    if ((n = (heapnode *) __mp_getslot(&h->table)) == NULL)
    {
        s = h->memory.page * MP_ALLOCFACTOR;
        if ((p = __mp_memalloc(&h->memory, &s, h->table.entalign, 0)) == NULL)
            return NULL;
        __mp_initslots(&h->table, p, s);
        n = (heapnode *) __mp_getslot(&h->table);
        __mp_treeinsert(&h->itree, &n->node, (unsigned long) p);
        n->block = p;
        n->size = s;
        h->isize += s;
        if (h->tracing)
            __mp_traceheap(p, s, 1);
#if MP_INUSE_SUPPORT
        _Inuse_heapalloc(p, s);
#endif /* MP_INUSE_SUPPORT */
        n = (heapnode *) __mp_getslot(&h->table);
    }
    /* Allocate the requested block of memory and add it to the heap.
     */
    if ((p = __mp_memalloc(&h->memory, &l, a, !i)) == NULL)
    {
        __mp_freeslot(&h->table, n);
        return NULL;
    }
    __mp_treeinsert(&h->dtree, &n->node, (unsigned long) p);
    n->block = p;
    n->size = l;
    h->dsize += l;
    if (h->tracing)
        __mp_traceheap(p, l, i);
#if MP_INUSE_SUPPORT
    _Inuse_heapalloc(p, l);
#endif /* MP_INUSE_SUPPORT */
    return n;
}
Ejemplo n.º 4
0
/* Read an event from the tracing output file.
 */

#if MP_GUI_SUPPORT
static
int
readevent(XtPointer p)
#else /* MP_GUI_SUPPORT */
static
int
readevent(void)
#endif /* MP_GUI_SUPPORT */
{
    char s[4];
    allocation *f;
    char *g, *h;
    void *a;
    size_t i, l, m;
    unsigned long n, t, u;

    if (refill(1))
        switch (*bufferpos)
        {
          case 'A':
            bufferpos++;
            bufferlen--;
            currentevent++;
            n = getuleb128();
            a = (void *) getuleb128();
            l = getuleb128();
            getsource(&t, &g, &h, &u);
            f = newalloc(n, currentevent, a, l);
            stats.acount++;
            stats.atotal += l;
            if (stats.pcount < stats.acount - stats.fcount)
                stats.pcount = stats.acount - stats.fcount;
            if (stats.ptotal < stats.atotal - stats.ftotal)
                stats.ptotal = stats.atotal - stats.ftotal;
            if ((stats.lsize == 0) || (stats.lsize > l))
                stats.lsize = l;
            if (stats.usize < l)
                stats.usize = l;
            if (verbose)
            {
                fprintf(stdout, "%6lu  alloc   %6lu  " MP_POINTER "  %8lu"
                        "          %6lu  %8lu\n", currentevent, n, a, l,
                        stats.acount - stats.fcount,
                        stats.atotal - stats.ftotal);
                if (displaysource)
                    printsource(t, g, h, u);
            }
            if (hatffile != NULL)
                fprintf(hatffile, "1 %lu 0x%lx\n", l, a);
            if (f->entry != NULL)
            {
                if ((m = slotentry(f)) > maxslots)
                    maxslots = m;
                fprintf(simfile, "    {%lu, %lu, 0},\n", m, l);
            }
#if MP_GUI_SUPPORT
            if (usegui)
            {
                if (addrbase == NULL)
                    addrbase = (void *) __mp_rounddown((unsigned long) a, 1024);
                drawmemory(a, l, algc);
                return 0;
            }
#endif /* MP_GUI_SUPPORT */
            return 1;
          case 'R':
            bufferpos++;
            bufferlen--;
            currentevent++;
            n = getuleb128();
            a = (void *) getuleb128();
            l = getuleb128();
            getsource(&t, &g, &h, &u);
            if (f = (allocation *) __mp_search(alloctree.root, n))
            {
                if (f->time != 0)
                    fprintf(stderr, "%s: Allocation index `%lu' has already "
                            "been freed\n", progname, n);
                stats.acount++;
                stats.atotal += l;
                stats.fcount++;
                stats.ftotal += f->size;
                if (stats.pcount < stats.acount - stats.fcount)
                    stats.pcount = stats.acount - stats.fcount;
                if (stats.ptotal < stats.atotal - stats.ftotal)
                    stats.ptotal = stats.atotal - stats.ftotal;
                if ((stats.lsize == 0) || (stats.lsize > l))
                    stats.lsize = l;
                if (stats.usize < l)
                    stats.usize = l;
                if (verbose)
                {
                    fprintf(stdout, "%6lu  realloc %6lu  " MP_POINTER
                            "  %8lu          %6lu  %8lu\n", currentevent, n, a,
                            l, stats.acount - stats.fcount,
                            stats.atotal - stats.ftotal);
                    if (displaysource)
                        printsource(t, g, h, u);
                }
                if (hatffile != NULL)
                    fprintf(hatffile, "4 %lu 0x%lx 0x%lx\n", l, f->addr, a);
                if (f->entry != NULL)
                {
                    m = slotentry(f);
                    fprintf(simfile, "    {%lu, %lu, 1},\n", m, l);
                }
#if MP_GUI_SUPPORT
                if (usegui)
                {
                    drawmemory(f->addr, f->size, frgc);
                    drawmemory(a, l, algc);
                }
#endif /* MP_GUI_SUPPORT */
                f->addr = a;
                f->size = l;
            }
            else
                fprintf(stderr, "%s: Unknown allocation index `%lu'\n",
                        progname, n);
#if MP_GUI_SUPPORT
            if (usegui)
                return 0;
#endif /* MP_GUI_SUPPORT */
            return 1;
          case 'F':
            bufferpos++;
            bufferlen--;
            currentevent++;
            n = getuleb128();
            getsource(&t, &g, &h, &u);
            if (f = (allocation *) __mp_search(alloctree.root, n))
            {
                if (f->time != 0)
                    fprintf(stderr, "%s: Allocation index `%lu' has already "
                            "been freed\n", progname, n);
                f->time = currentevent - f->event;
                stats.fcount++;
                stats.ftotal += f->size;
                if (verbose)
                {
                    fprintf(stdout, "%6lu  free    %6lu  " MP_POINTER "  %8lu  "
                            "%6lu  %6lu  %8lu\n", currentevent, n, f->addr,
                            f->size, f->time, stats.acount - stats.fcount,
                            stats.atotal - stats.ftotal);
                    if (displaysource)
                        printsource(t, g, h, u);
                }
                if (hatffile != NULL)
                    fprintf(hatffile, "2 0x%lx\n", f->addr);
                if (f->entry != NULL)
                {
                    fprintf(simfile, "    {%lu, 0, 0},\n", slotentry(f));
                    __mp_freeslot(&table, f->entry);
                    f->entry = NULL;
                }
#if MP_GUI_SUPPORT
                if (usegui)
                    drawmemory(f->addr, f->size, frgc);
#endif /* MP_GUI_SUPPORT */
            }
            else
                fprintf(stderr, "%s: Unknown allocation index `%lu'\n",
                        progname, n);
#if MP_GUI_SUPPORT
            if (usegui)
                return 0;
#endif /* MP_GUI_SUPPORT */
            return 1;
          case 'H':
            bufferpos++;
            bufferlen--;
            a = (void *) getuleb128();
            l = getuleb128();
            if (verbose)
                fprintf(stdout, "        reserve         " MP_POINTER
                        "  %8lu\n", a, l);
            stats.rcount++;
            stats.rtotal += l;
#if MP_GUI_SUPPORT
            if (usegui)
            {
                if (addrbase == NULL)
                    addrbase = (void *) __mp_rounddown((unsigned long) a, 1024);
                drawmemory(a, l, frgc);
                return 0;
            }
#endif /* MP_GUI_SUPPORT */
            return 1;
          case 'I':
            bufferpos++;
            bufferlen--;
            a = (void *) getuleb128();
            l = getuleb128();
            if (verbose)
                fprintf(stdout, "        internal        " MP_POINTER
                        "  %8lu\n", a, l);
            stats.icount++;
            stats.itotal += l;
#if MP_GUI_SUPPORT
            if (usegui)
            {
                drawmemory(a, l, ingc);
                return 0;
            }
#endif /* MP_GUI_SUPPORT */
            return 1;
          default:
            break;
        }
    if ((hatffile != NULL) && (hatffile != stdout) && (hatffile != stderr))
        fclose(hatffile);
    if (simfile != NULL)
    {
        fputs("    {0, 0, 0}\n};\n\n\n", simfile);
        fputs("int main(void)\n{\n", simfile);
        fprintf(simfile, "    void *p[%lu];\n", maxslots);
        fputs("    event *e;\n\n", simfile);
        fputs("    for (e = events; e->index != 0; e++)\n", simfile);
        fputs("        if (e->resize)\n", simfile);
        fputs("        {\n", simfile);
        fputs("            if ((p[e->index - 1] = realloc(p[e->index - 1], "
              "e->size)) == NULL)\n", simfile);
        fputs("            {\n", simfile);
        fputs("                fputs(\"out of memory\\n\", stderr);\n",
                                     simfile);
        fputs("                exit(EXIT_FAILURE);\n", simfile);
        fputs("            }\n", simfile);
        fputs("        }\n", simfile);
        fputs("        else if (e->size == 0)\n", simfile);
        fputs("            free(p[e->index - 1]);\n", simfile);
        fputs("        else if ((p[e->index - 1] = malloc(e->size)) == NULL)\n",
              simfile);
        fputs("        {\n", simfile);
        fputs("            fputs(\"out of memory\\n\", stderr);\n", simfile);
        fputs("            exit(EXIT_FAILURE);\n", simfile);
        fputs("        }\n", simfile);
        fputs("    return EXIT_SUCCESS;\n}\n", simfile);
        if ((simfile != stdout) && (simfile != stderr))
            fclose(simfile);
    }
    getentry(s, sizeof(char), 4, 0);
    if (memcmp(s, MP_TRACEMAGIC, 4) != 0)
    {
        fprintf(stderr, "%s: Invalid file format\n", progname);
        exit(EXIT_FAILURE);
    }
    if (verbose)
        fputc('\n', stdout);
    showstats();
    for (i = 0; i < MP_NAMECACHE_SIZE; i++)
    {
        if (funcnames[i] != NULL)
            free(funcnames[i]);
        if (filenames[i] != NULL)
            free(filenames[i]);
    }
    freeallocs();
    fclose(tracefile);
#if MP_GUI_SUPPORT
    if (usegui)
        return 1;
#endif /* MP_GUI_SUPPORT */
    return 0;
}
Ejemplo n.º 5
0
MP_GLOBAL
int
__mp_resizealloc(allochead *h, allocnode *n, size_t l)
{
    allocnode *p;
    size_t m, s;
    long d;

    /* If all allocations are pages and the allocations are to be aligned
     * to the end of a page then the easiest solution is to fail here since
     * the majority of cases would require relocation of the original memory
     * allocation.
     */
    if ((h->flags & FLG_PAGEALLOC) && (h->flags & FLG_ALLOCUPPER))
        return 0;
    if (l == 0)
        l = 1;
    d = l - n->size;
    /* If we are allocating pages then the effective block size is the
     * original size rounded up to a multiple of the system page size.
     */
    if (h->flags & FLG_PAGEALLOC)
        m = __mp_roundup(n->size, h->heap.memory.page);
    else
        m = n->size;
    /* Obtain the bordering free node to the right of this node, if one
     * exists.  There is no need to look any further right as it is
     * guaranteed that it will not be another bordering free node.
     */
    p = (allocnode *) n->lnode.next;
    if ((p->lnode.next == NULL) || (p->info != NULL) ||
        ((char *) n->block + m + h->oflow < (char *) p->block))
        p = NULL;
    if ((h->flags & FLG_PAGEALLOC) && (l <= m) && (l > m - h->heap.memory.page))
    {
        /* There is space in the existing allocated pages to perform the
         * resize without requiring the modification or creation of a
         * neighbouring free node so we remove the watch point area if it
         * exists.
         */
        if (h->flags & FLG_OFLOWWATCH)
            __mp_memwatch(&h->heap.memory, (char *) n->block + n->size,
                          m - n->size, MA_READWRITE);
    }
    else if (d > 0)
    {
        /* If the request was to increase the size of the node and we have no
         * suitable node to merge with or the total size of both nodes is still
         * too small then we just fail.  The relocation to a larger memory
         * allocation is done by the calling function.
         */
        if ((p == NULL) || (m + p->size < l))
            return 0;
        __mp_treeremove(&h->ftree, &p->tnode);
        if (h->flags & FLG_PAGEALLOC)
        {
            s = __mp_roundup(l, h->heap.memory.page) - m;
            /* Remove any memory protection and the watch point area if it
             * exists.
             */
            __mp_memprotect(&h->heap.memory, (char *) p->block - h->oflow, s,
                            MA_READWRITE);
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, (char *) n->block + n->size,
                              m - n->size, MA_READWRITE);
        }
        else
        {
            s = d;
            /* Remove the right-most watch point area if it exists.
             */
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, (char *) n->block + m, h->oflow,
                              MA_READWRITE);
        }
        p->block = (char *) p->block + s;
        p->size -= s;
        /* If the resulting size of the free block we merged with is zero then
         * we can just delete it, otherwise we must insert it back into the
         * free tree.
         */
        if (p->size == 0)
        {
            __mp_remove(&h->list, &p->lnode);
            __mp_freeslot(&h->table, p);
        }
        else
            __mp_treeinsert(&h->ftree, &p->tnode, p->size);
        h->fsize -= s;
    }
    else if (d < 0)
    {
        /* If the request was to decrease the size of the node then we
         * must either increase the size of the bordering node, or create
         * a new free node.
         */
        if (p == NULL)
        {
            if ((p = getnode(h)) == NULL)
                return 0;
            __mp_insert(&h->list, &n->lnode, &p->lnode);
            p->block = (char *) n->block + m + h->oflow;
            p->size = 0;
            p->info = NULL;
        }
        else
            __mp_treeremove(&h->ftree, &p->tnode);
        if (h->flags & FLG_PAGEALLOC)
        {
            s = m - __mp_roundup(l, h->heap.memory.page);
            /* Remove the watch point area if it exists.
             */
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, (char *) n->block + n->size,
                              m - n->size, MA_READWRITE);
        }
        else
        {
            s = -d;
            /* Remove the right-most watch point area if it exists.
             */
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, (char *) n->block + m, h->oflow,
                              MA_READWRITE);
        }
        p->block = (char *) p->block - s;
        p->size += s;
        if (h->flags & FLG_PAGEALLOC)
            __mp_memprotect(&h->heap.memory, p->block, s, MA_NOACCESS);
        else
            __mp_memset(p->block, h->fbyte, s);
        __mp_treeinsert(&h->ftree, &p->tnode, p->size);
        h->fsize += s;
    }
    if (h->flags & FLG_PAGEALLOC)
    {
        s = __mp_roundup(l, h->heap.memory.page) - l;
        if (h->flags & FLG_OFLOWWATCH)
            __mp_memwatch(&h->heap.memory, (char *) n->block + l, s,
                          MA_NOACCESS);
        else
            __mp_memset((char *) n->block + l, h->obyte, s);
    }
    else if (h->flags & FLG_OFLOWWATCH)
        __mp_memwatch(&h->heap.memory, (char *) n->block + l, h->oflow,
                      MA_NOACCESS);
    else
        __mp_memset((char *) n->block + l, h->obyte, h->oflow);
    n->size = l;
    h->asize += d;
    return 1;
}
Ejemplo n.º 6
0
MP_GLOBAL
allocnode *
__mp_getalloc(allochead *h, size_t l, size_t a, void *i)
{
    allocnode *n, *r, *s;
    heapnode *p;
    treenode *t;
    size_t b, m;

    b = h->oflow << 1;
    if (l == 0)
        l = 1;
    if (a == 0)
        a = h->heap.memory.align;
    else if (a > h->heap.memory.page)
        a = h->heap.memory.page;
    else
        a = __mp_poweroftwo(a);
    /* If all allocations are not pages then we must add more bytes to the
     * allocation request to account for alignment.
     */
    if (h->flags & FLG_PAGEALLOC)
        m = 0;
    else
        m = a - 1;
    /* If we have no suitable space for this allocation then we must allocate
     * memory via the heap manager.
     */
    if ((t = __mp_searchhigher(h->ftree.root, l + b + m)) == NULL)
    {
        if ((n = getnode(h)) == NULL)
            return NULL;
        /* If all allocations are pages then we must specify that we want our
         * heap allocation to be page-aligned.
         */
        if (h->flags & FLG_PAGEALLOC)
            m = h->heap.memory.page;
        else
            m = a;
        if ((p = __mp_heapalloc(&h->heap,
              __mp_roundup(l + b, h->heap.memory.page), m, 0)) == NULL)
        {
            __mp_freeslot(&h->table, n);
            return NULL;
        }
        /* Initialise the free memory.  If all allocations are pages then we
         * prevent any free memory from being both read from and written to.
         */
        if (h->flags & FLG_PAGEALLOC)
            __mp_memprotect(&h->heap.memory, p->block, p->size, MA_NOACCESS);
        else
            __mp_memset(p->block, h->fbyte, p->size);
        /* Insert the new memory block into the correct position in the
         * memory block list.  This is vital for merging free nodes.
         */
        if ((t = __mp_searchlower(h->atree.root, (unsigned long) p->block)) ||
            (t = __mp_searchlower(h->gtree.root, (unsigned long) p->block)))
            r = (allocnode *) ((char *) t - offsetof(allocnode, tnode));
        else
            r = (allocnode *) &h->list;
        while (((s = (allocnode *) r->lnode.next)->lnode.next != NULL) &&
               (s->block < p->block))
            r = s;
        __mp_insert(&h->list, &r->lnode, &n->lnode);
        __mp_treeinsert(&h->ftree, &n->tnode, p->size);
        n->block = p->block;
        n->size = p->size;
        n->info = NULL;
        h->fsize += p->size;
        /* Merge the memory block with any bordering free nodes.  This
         * is also vital to maintain the property that the memory block
         * list does not ever contain two bordering free nodes.
         */
        n = mergenode(h, n);
    }
    else
        n = (allocnode *) ((char *) t - offsetof(allocnode, tnode));
    /* Split the free node as requested.
     */
    return splitnode(h, n, l, a, i);
}
Ejemplo n.º 7
0
static
allocnode *
splitnode(allochead *h, allocnode *n, size_t l, size_t a, void *i)
{
    allocnode *p, *q;
    size_t m, s;

    /* We choose the worst case scenario here and allocate new nodes for
     * both the left and right nodes.  This is so that we can easily recover
     * from lack of system memory at this point rather than rebuild the
     * original free node if we discover that we are out of memory later.
     */
    if (((p = getnode(h)) == NULL) || ((q = getnode(h)) == NULL))
    {
        if (p != NULL)
            __mp_freeslot(&h->table, p);
        return NULL;
    }
    /* Remove the free node from the free tree.
     */
    __mp_treeremove(&h->ftree, &n->tnode);
    h->fsize -= n->size;
    n->block = (char *) n->block + h->oflow;
    n->size -= h->oflow << 1;
    /* Check to see if we have space left over to create a free node to the
     * left of the new node.  This is never done if all allocations are pages.
     */
    if (!(h->flags & FLG_PAGEALLOC) &&
        ((m = __mp_roundup((unsigned long) n->block, a) -
          (unsigned long) n->block) > 0))
    {
        __mp_prepend(&h->list, &n->lnode, &p->lnode);
        __mp_treeinsert(&h->ftree, &p->tnode, m);
        p->block = (char *) n->block - h->oflow;
        p->size = m;
        p->info = NULL;
        n->block = (char *) n->block + m;
        n->size -= m;
        h->fsize += m;
    }
    else
        __mp_freeslot(&h->table, p);
    /* If we are allocating pages then the effective block size is the
     * original size rounded up to a multiple of the system page size.
     */
    if (h->flags & FLG_PAGEALLOC)
        s = __mp_roundup(l, h->heap.memory.page);
    else
        s = l;
    /* Check to see if we have space left over to create a free node to the
     * right of the new node.  This free node will always have a size which is
     * a multiple of the system page size if all allocations are pages.
     */
    if ((m = n->size - s) > 0)
    {
        __mp_insert(&h->list, &n->lnode, &q->lnode);
        __mp_treeinsert(&h->ftree, &q->tnode, m);
        q->block = (char *) n->block + s + h->oflow;
        q->size = m;
        q->info = NULL;
        n->size = s;
        h->fsize += m;
    }
    else
        __mp_freeslot(&h->table, q);
    /* Initialise the details of the newly allocated node and insert it in
     * the allocation tree.
     */
    n->info = i;
    if (h->flags & FLG_PAGEALLOC)
    {
        __mp_memprotect(&h->heap.memory, n->block, n->size, MA_READWRITE);
        /* If we are aligning the end of allocations to the upper end of pages
         * then we may have to shift the start of the block up by a certain
         * number of bytes.  This will then also lead to us having to prefill
         * the unused space with the overflow byte or place a watch point area
         * there.
         */
        if ((h->flags & FLG_ALLOCUPPER) &&
            ((m = __mp_rounddown(n->size - l, a)) > 0))
        {
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, n->block, m, MA_NOACCESS);
            else
                __mp_memset(n->block, h->obyte, m);
            n->block = (char *) n->block + m;
            n->size -= m;
        }
        /* We may need to prefill any unused space at the end of the block with
         * the overflow byte, or place a watch point area there.
         */
        if ((m = n->size - l) > 0)
        {
            if (h->flags & FLG_OFLOWWATCH)
                __mp_memwatch(&h->heap.memory, (char *) n->block + l, m,
                              MA_NOACCESS);
            else
                __mp_memset((char *) n->block + l, h->obyte, m);
        }
        n->size = l;
    }
    else if (h->flags & FLG_OFLOWWATCH)
    {
        __mp_memwatch(&h->heap.memory, (char *) n->block - h->oflow, h->oflow,
                      MA_NOACCESS);
        __mp_memwatch(&h->heap.memory, (char *) n->block + n->size, h->oflow,
                      MA_NOACCESS);
    }
    else
    {
        __mp_memset((char *) n->block - h->oflow, h->obyte, h->oflow);
        __mp_memset((char *) n->block + n->size, h->obyte, h->oflow);
    }
    __mp_treeinsert(&h->atree, &n->tnode, (unsigned long) n->block);
    h->asize += n->size;
    return n;
}