(У цьому підсумку не пояснюються перевірки, і деякі випадки були опущені для стислості)
__libc_malloc намагається отримати шматок з tcache, якщо ні, викликає _int_malloc
_int_malloc :
Намагається створити арену, якщо її немає
Якщо є шматок з швидкого біну правильного розміру, використовує його
Заповнює tcache іншими швидкими шматками
Якщо є шматок з малого біну правильного розміру, використовує його
Заповнює tcache іншими шматками цього розміру
Якщо запитуваний розмір не для малих бінів, консолідує швидкий бін в неупорядкований бін
Перевіряє неупорядкований бін, використовує перший шматок з достатнім місцем
Якщо знайдений шматок більший, ділить його, щоб повернути частину, і додає залишок назад до неупорядкованого біна
Якщо шматок того ж розміру, що й запитуваний, використовує його для заповнення tcache замість повернення (поки tcache не заповниться, потім повертає наступний)
Для кожного перевіреного шматка меншого розміру, поміщає його в його відповідний малий або великий бін
Перевіряє великий бін за індексом запитуваного розміру
Починає шукати з першого шматка, який більший за запитуваний розмір, якщо знайдено, повертає його і додає залишки до малого біна
Перевіряє великі біни з наступних індексів до кінця
З наступного більшого індексу перевіряє наявність будь-якого шматка, ділить перший знайдений шматок, щоб використовувати його для запитуваного розміру, і додає залишок до неупорядкованого біна
Якщо нічого не знайдено в попередніх бінах, отримує шматок з верхнього шматка
Якщо верхній шматок не був достатньо великим, розширює його за допомогою sysmalloc
__libc_malloc
Функція malloc насправді викликає __libc_malloc. Ця функція перевіряє tcache, щоб дізнатися, чи є доступний шматок бажаного розміру. Якщо є, вона використовує його, а якщо ні, перевіряє, чи це однопотокова програма, і в цьому випадку викликає _int_malloc в основній арені, а якщо ні, викликає _int_malloc в арені потоку.
__libc_malloc код
```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
Це функція, яка виділяє пам'ять, використовуючи інші контейнери та верхній шматок.
Початок
Вона починає з визначення деяких змінних і отримання реального розміру, який потрібно для запитуваного простору пам'яті:
Fast Bin
Якщо потрібний розмір знаходиться в межах розмірів Fast Bins, спробуйте використати шматок з швидкого бін. В основному, на основі розміру, він знайде індекс швидкого біна, де повинні бути розташовані дійсні шматки, і, якщо такі є, поверне один з них.
Більше того, якщо tcache увімкнено, він заповнить бін tcache цього розміру швидкими бінами.
Під час виконання цих дій тут виконуються деякі перевірки безпеки:
Якщо шматок неправильно вирівняний: malloc(): unaligned fastbin chunk detected 2
Якщо наступний шматок неправильно вирівняний: malloc(): unaligned fastbin chunk detected
Якщо повернутий шматок має неправильний розмір через свій індекс у швидкому біні: malloc(): memory corruption (fast)
Якщо будь-який шматок, використаний для заповнення tcache, неправильно вирівняний: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
Якщо це не маленький шматок, це великий шматок, і в цьому випадку викликається malloc_consolidate, щоб уникнути фрагментації пам'яті.
Невпорядкований бін
Час перевірити невпорядкований бін на наявність потенційно дійсного шматка для використання.
Початок
Це починається з великого циклу for, який буде проходити через невпорядкований бін у напрямку bk, поки не досягне кінця (структура арени) з 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 (арена): malloc(): unsorted double linked list corrupted
Оскільки ми завжди перевіряємо останній, його fd завжди має вказувати на структуру арени.
Якщо наступний шматок не вказує, що попередній використовується: malloc(): invalid next->prev_inuse (unsorted)
Якщо це було успішно, поверніть шматок і все, якщо ні, продовжуйте виконувати функцію...
якщо однаковий розмір
Продовжуйте видаляти шматок з бін, у разі якщо запитуваний розмір точно відповідає розміру шматка:
Якщо tcache не заповнений, додайте його до tcache і продовжте вказувати, що є шматок tcache, який можна використовувати
Якщо tcache заповнений, просто використайте його, повертаючи його
_int_malloc обмеження
На цьому етапі, якщо якийсь шматок був збережений у tcache, який можна використовувати, і досягнуто обмеження, просто поверніть шматок з tcache.
Більше того, якщо досягнуто MAX_ITERS, вийдіть з циклу і отримайте шматок іншим способом (top chunk).
Якщо return_cached було встановлено, просто поверніть шматок з tcache, щоб уникнути більших пошуків.
Якщо шматок не знайдено підходящим для цього, продовжуйте
Велика корзина (наступна більша)
Якщо в точно великій корзині не було жодного шматка, який можна було б використати, почніть перебір усіх наступних великих корзин (починаючи з найбільшого) до тих пір, поки не буде знайдено один (якщо є).
Залишок розділеного шматка додається в неупорядковану корзину, last_reminder оновлюється, і виконується та ж сама перевірка безпеки:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc початок
Якщо арена є нульовою або запитуваний розмір занадто великий (і залишилися дозволені 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;