(Δεν εξηγούνται έλεγχοι σε αυτή την περίληψη και ορισμένες περιπτώσεις έχουν παραληφθεί για συντομία)
__libc_malloc προσπαθεί να πάρει ένα κομμάτι από το tcache, αν όχι καλεί το _int_malloc
_int_malloc :
Προσπαθεί να δημιουργήσει την αρένα αν δεν υπάρχει
Αν υπάρχει κάποιο γρήγορο κομμάτι της σωστής διάστασης, το χρησιμοποιεί
Γεμίζει το tcache με άλλα γρήγορα κομμάτια
Αν υπάρχει κάποιο μικρό κομμάτι της σωστής διάστασης, το χρησιμοποιεί
Γεμίζει το tcache με άλλα κομμάτια αυτής της διάστασης
Αν η ζητούμενη διάσταση δεν είναι για μικρές αρένες, ενοποιεί το γρήγορο κομμάτι σε ακατάτακτο κομμάτι
Ελέγχει το ακατάτακτο κομμάτι, χρησιμοποιεί το πρώτο κομμάτι με αρκετό χώρο
Αν το βρεθέν κομμάτι είναι μεγαλύτερο, το διαιρεί για να επιστρέψει ένα μέρος και προσθέτει το υπόλοιπο πίσω στο ακατάτακτο κομμάτι
Αν ένα κομμάτι είναι της ίδιας διάστασης με τη ζητούμενη διάσταση, το χρησιμοποιεί για να γεμίσει το tcache αντί να το επιστρέψει (μέχρι το tcache να είναι γεμάτο, τότε επιστρέφει το επόμενο)
Για κάθε κομμάτι μικρότερης διάστασης που ελέγχεται, το τοποθετεί στην αντίστοιχη μικρή ή μεγάλη αρένα
Ελέγχει τη μεγάλη αρένα στον δείκτη της ζητούμενης διάστασης
Ξεκινά να κοιτά από το πρώτο κομμάτι που είναι μεγαλύτερο από τη ζητούμενη διάσταση, αν βρεθεί κάποιο το επιστρέφει και προσθέτει τα υπόλοιπα στη μικρή αρένα
Ελέγχει τις μεγάλες αρένες από τους επόμενους δείκτες μέχρι το τέλος
Από τον επόμενο μεγαλύτερο δείκτη ελέγχει για οποιοδήποτε κομμάτι, διαιρεί το πρώτο βρεθέν κομμάτι για να το χρησιμοποιήσει για τη ζητούμενη διάσταση και προσθέτει το υπόλοιπο στο ακατάτακτο κομμάτι
Αν δεν βρεθεί τίποτα στις προηγούμενες αρένες, παίρνει ένα κομμάτι από το κορυφαίο κομμάτι
Αν το κορυφαίο κομμάτι δεν ήταν αρκετά μεγάλο, το επεκτείνει με sysmalloc
__libc_malloc
Η συνάρτηση malloc στην πραγματικότητα καλεί το __libc_malloc. Αυτή η συνάρτηση θα ελέγξει το tcache για να δει αν υπάρχει διαθέσιμο κομμάτι της επιθυμητής διάστασης. Αν υπάρχει, θα το χρησιμοποιήσει και αν όχι, θα ελέγξει αν είναι μονός νήμα και σε αυτή την περίπτωση θα καλέσει το _int_malloc στην κύρια αρένα, και αν όχι θα καλέσει το _int_malloc στην αρένα του νήματος.
__libc_malloc code
```c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
victim = _int_malloc (ar_ptr, bytes); /* Retry with another arena only if we were able to find a usable arena before. */ if (!victim && ar_ptr != NULL) { LIBC_PROBE (memory_malloc_retry, 1, bytes); ar_ptr = arena_get_retry (ar_ptr, bytes); victim = _int_malloc (ar_ptr, bytes); }
if (ar_ptr != NULL) __libc_lock_unlock (ar_ptr->mutex);
</details>
Σημειώστε πώς θα επισημαίνει πάντα τον επιστρεφόμενο δείκτη με `tag_new_usable`, από τον κώδικα:
```c
void *tag_new_usable (void *ptr)
Allocate a new random color and use it to color the user region of
a chunk; this may include data from the subsequent chunk's header
if tagging is sufficiently fine grained. Returns PTR suitably
recolored for accessing the memory there.
_int_malloc
Αυτή είναι η συνάρτηση που εκχωρεί μνήμη χρησιμοποιώντας τα άλλα bins και το top chunk.
Έναρξη
Αρχίζει ορίζοντας μερικές μεταβλητές και αποκτώντας το πραγματικό μέγεθος που χρειάζεται να έχει ο ζητούμενος χώρος μνήμης:
Fast Bin
Αν το απαιτούμενο μέγεθος είναι μέσα στα μεγέθη των Fast Bins, προσπαθήστε να χρησιμοποιήσετε ένα chunk από το fast bin. Βασικά, με βάση το μέγεθος, θα βρει τον δείκτη του fast bin όπου θα πρέπει να βρίσκονται τα έγκυρα chunks, και αν υπάρχουν, θα επιστρέψει ένα από αυτά.
Επιπλέον, αν το tcache είναι ενεργοποιημένο, θα γεμίσει το tcache bin αυτού του μεγέθους με fast bins.
Κατά την εκτέλεση αυτών των ενεργειών, εκτελούνται μερικοί έλεγχοι ασφαλείας εδώ:
Αν το chunk είναι μη ευθυγραμμισμένο: malloc(): unaligned fastbin chunk detected 2
Αν το μπροστινό chunk είναι μη ευθυγραμμισμένο: malloc(): unaligned fastbin chunk detected
Αν το επιστρεφόμενο chunk έχει μέγεθος που δεν είναι σωστό λόγω του δείκτη του στο fast bin: malloc(): memory corruption (fast)
Αν οποιοδήποτε chunk που χρησιμοποιείται για να γεμίσει το tcache είναι μη ευθυγραμμισμένο: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
Αν δεν ήταν ένα μικρό κομμάτι, είναι ένα μεγάλο κομμάτι, και σε αυτή την περίπτωση καλείται malloc_consolidate για να αποφευχθεί η κατακερματισμένη μνήμη.
Αταξινόμητος κάδος
Ήρθε η ώρα να ελέγξουμε τον αταξινόμητο κάδο για μια πιθανή έγκυρη κομμάτι προς χρήση.
Έναρξη
Αυτό ξεκινά με έναν μεγάλο βρόχο for που θα διασχίζει τον αταξινόμητο κάδο στην κατεύθυνση bk μέχρι να φτάσει στο τέλος (τη δομή arena) με while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
Επιπλέον, γίνονται κάποιες ελέγχοι ασφαλείας κάθε φορά που εξετάζεται ένα νέο κομμάτι:
Αν το μέγεθος του κομματιού είναι περίεργο (πολύ μικρό ή πολύ μεγάλο): malloc(): invalid size (unsorted)
Αν το μέγεθος του επόμενου κομματιού είναι περίεργο (πολύ μικρό ή πολύ μεγάλο): malloc(): invalid next size (unsorted)
Αν το προηγούμενο μέγεθος που υποδεικνύεται από το επόμενο κομμάτι διαφέρει από το μέγεθος του κομματιού: malloc(): mismatching next->prev_size (unsorted)
Αν όχι victim->bck->fd == victim ή όχι victim->fd == av (arena): malloc(): unsorted double linked list corrupted
Καθώς πάντα ελέγχουμε το τελευταίο, το fd του θα πρέπει πάντα να δείχνει στη δομή arena.
Αν το επόμενο κομμάτι δεν υποδεικνύει ότι το προηγούμενο είναι σε χρήση: malloc(): invalid next->prev_inuse (unsorted)
Αν αυτό ήταν επιτυχές, επιστρέψτε το chunk και τελειώστε, αν όχι, συνεχίστε την εκτέλεση της συνάρτησης...
αν ίσου μεγέθους
Συνεχίστε να αφαιρείτε το chunk από το bin, σε περίπτωση που το ζητούμενο μέγεθος είναι ακριβώς το ίδιο με αυτό του chunk:
Αν το tcache δεν είναι γεμάτο, προσθέστε το στο tcache και συνεχίστε υποδεικνύοντας ότι υπάρχει ένα tcache chunk που θα μπορούσε να χρησιμοποιηθεί
Αν το tcache είναι γεμάτο, απλώς χρησιμοποιήστε το επιστρέφοντάς το
_int_malloc όρια
Σε αυτό το σημείο, αν κάποιο κομμάτι αποθηκεύτηκε στο tcache που μπορεί να χρησιμοποιηθεί και το όριο έχει φτάσει, απλά επιστρέφει ένα κομμάτι από το tcache.
Επιπλέον, αν MAX_ITERS έχει φτάσει, σπάστε από τον βρόχο και αποκτήστε ένα κομμάτι με διαφορετικό τρόπο (top chunk).
Αν το return_cached έχει οριστεί, απλά επιστρέψτε ένα κομμάτι από το tcache για να αποφύγετε μεγαλύτερες αναζητήσεις.
Αν δεν βρεθεί κατάλληλο chunk για αυτό, συνεχίστε
Μεγάλος Κάδος (επόμενος μεγαλύτερος)
Αν στον ακριβή μεγάλο κάδο δεν υπήρχε κανένα chunk που να μπορεί να χρησιμοποιηθεί, αρχίστε να επαναλαμβάνετε όλους τους επόμενους μεγάλους κάδους (ξεκινώντας από τον αμέσως μεγαλύτερο) μέχρι να βρεθεί ένα (αν υπάρχει).
Το υπόλοιπο του διαχωρισμένου chunk προστίθεται στον αταξινόμητο κάδο, το last_reminder ενημερώνεται και η ίδια έλεγχος ασφαλείας εκτελείται:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc αρχή
Αν η αρένα είναι null ή το ζητούμενο μέγεθος είναι πολύ μεγάλο (και υπάρχουν mmaps που επιτρέπονται) χρησιμοποίησε sysmalloc_mmap για να εκχωρήσεις χώρο και να τον επιστρέψεις.
sysmalloc όχι κύρια αρένα
Θα προσπαθήσει πρώτα να επεκτείνει την προηγούμενη σωρό για αυτή τη σωρό. Αν δεν είναι δυνατή, θα προσπαθήσει να κατανείμει μια νέα σωρό και να ενημερώσει τους δείκτες για να μπορέσει να τη χρησιμοποιήσει.
Τέλος, αν αυτό δεν λειτουργήσει, προσπαθήστε να καλέσετε sysmalloc_mmap.
sysmalloc κύρια αρένα προηγούμενο σφάλμα 1
Εάν το προηγούμενο επιστράφηκε MORECORE_FAILURE, προσπαθήστε ξανά να εκχωρήσετε μνήμη χρησιμοποιώντας sysmalloc_mmap_fallback
sysmalloc finale
Ολοκληρώστε την κατανομή ενημερώνοντας τις πληροφορίες της αρένας
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2921C3-L2943C12if ((unsignedlong) av->system_mem > (unsignedlong) (av->max_system_mem))av->max_system_mem = av->system_mem;check_malloc_state (av);/* finally, do the allocation */p = av->top;size =chunksize (p);/* check that one of the above allocation paths succeeded */if ((unsignedlong) (size) >= (unsignedlong) (nb + MINSIZE)){remainder_size = size - nb;remainder =chunk_at_offset (p, nb);av->top = remainder;set_head (p, nb | PREV_INUSE | (av !=&main_arena ? NON_MAIN_ARENA :0));set_head (remainder, remainder_size | PREV_INUSE);check_malloced_chunk (av, p, nb);returnchunk2mem (p);}/* catch all failure paths */__set_errno (ENOMEM);return0;