malloc & sysmalloc
Огляд порядку виділення
(У цьому огляді не пояснюються перевірки, і деякі випадки були пропущені для кратності)
__libc_malloc
намагається отримати фрагмент з tcache, якщо немає, воно викликає_int_malloc
_int_malloc
:Намагається створити арену, якщо її немає
Якщо є будь-який швидкий фрагмент відповідного розміру, використовуйте його
Заповніть tcache іншими швидкими фрагментами
Якщо є будь-який фрагмент малих бінів відповідного розміру, використовуйте його
Заповніть tcache іншими фрагментами цього розміру
Якщо запитаний розмір не для малих бінів, об'єднайте швидкий бін в неупорядкований бін
Перевірте неупорядкований бін, використовуйте перший фрагмент з достатньою пам'яттю
Якщо знайдений фрагмент більший, розділіть його, щоб повернути частину та додати нагадування назад до неупорядкованого біна
Якщо фрагмент має такий самий розмір, як запитаний розмір, використовуйте його для заповнення tcache замість повернення його (доки tcache не буде повна, тоді поверніть наступний)
Для кожного перевіреного фрагмента меншого розміру, розмістіть його в відповідний малий або великий бін
Перевірте великий бін за індексом запитаного розміру
Почніть переглядати з першого фрагмента, який більший за запитаний розмір, якщо знайдете, поверніть його та додайте нагадування до малого біна
Перевірте великі біни з наступних індексів до кінця
З наступного більшого індексу перевірте будь-який фрагмент, розділіть перший знайдений фрагмент, щоб використовувати його для запитаного розміру та додати нагадування до неупорядкованого біна
Якщо в попередніх бінах нічого не знайдено, отримайте фрагмент з верхнього фрагмента
Якщо верхній фрагмент не був достатньо великим, збільште його за допомогою
sysmalloc
__libc_malloc
Функція malloc
фактично викликає __libc_malloc
. Ця функція перевіряє tcache, щоб переконатися, чи є доступний фрагмент потрібного розміру. Якщо є, вона використовує його, а якщо немає, вона перевіряє, чи це однопотокове середовище, і в цьому випадку вона викликає _int_malloc
в основній арені, а якщо ні, вона викликає _int_malloc
в арені потоку.
Якщо блок не повернуто або не додано до tcache, продовжуйте з кодом...
помістіть блок у бін
Збережіть перевірений блок у малий бін або у великий бін в залежності від розміру блоку (зберігаючи великий бін належним чином організованим).
Виконуються перевірки безпеки, щоб переконатися, що обидва подвійні зв'язані списки великого біна пошкоджені:
Якщо
fwd->bk_nextsize->fd_nextsize != fwd
:malloc(): великий бін подвійний зв'язаний список пошкоджений (nextsize)
Якщо
fwd->bk->fd != fwd
:malloc(): великий бін подвійний зв'язаний список пошкоджений (bk)
Якщо ліміт не досягнуто, продовжуйте з кодом...
Великий бін (за індексом)
Якщо запит великий (не в малий бін) і ми ще не повертали жодного чанка, отримуємо індекс запитаного розміру в великому біні, перевіряємо, чи не порожній він або чи найбільший чанк в цьому біні більший, ніж запитаний розмір, і в такому випадку знаходимо найменший чанк, який можна використати для запитаного розміру.
Якщо залишковий простір від кінцевого використаного чанка може бути новим чанком, додайте його до неупорядкованого біну, і оновлюється останній залишок.
При додаванні залишку до неупорядкованого біну виконується перевірка безпеки:
bck->fd-> bk != bck
:malloc(): corrupted unsorted chunks
Верхній чанк
На цьому етапі настав час отримати новий чанк з Верхнього чанку (якщо він достатньо великий).
Це починається з перевірки безпеки, щоб переконатися, що розмір чанку не є занадто великим (пошкодженим):
chunksize(av->top) > av->system_mem
:malloc(): corrupted top size
Потім він використовує простір верхнього чанку, якщо він достатньо великий, щоб створити чанк потрібного розміру.
Якщо ні, якщо є швидкі чанки, їх консолідують і спробують ще раз.
Нарешті, якщо місця недостатньо, використовується sysmalloc
для виділення достатнього розміру.
Перевірки sysmalloc
Це починається з отримання інформації про старий верхній фрагмент та перевірки того, що деякі з наступних умов є вірними:
Розмір старого купи нульовий (нова купа)
Розмір попередньої купи більший за MINSIZE, а старий Верх використовується
Купа вирівняна за розміром сторінки (0x1000, тому нижні 12 бітів повинні бути нульовими)
Потім також перевіряється, що:
Старий розмір не має достатньо місця для створення фрагмента потрібного розміру