Більшість реалізацій функцій розподілу пам’яті C зберігатимуть облікову інформацію для кожного блоку, або в рядку, або окремо.
Один типовий спосіб (рядковий) - це фактично розподілити як заголовок, так і пам’ять, про яку ви просили, доповнивши деякий мінімальний розмір. Наприклад, якщо ви попросили 20 байт, система може виділити 48-байтний блок:
- 16-байтний заголовок, що містить розмір, спеціальний маркер, контрольну суму, покажчики на наступний / попередній блок тощо.
- 32 байт області даних (ваші 20 байтів підкреслені кратним 16).
Тоді надана вам адреса - це адреса області даних. Тоді, коли ви звільнете блок, free
просто візьмете адресу, яку ви вказали, і, припустивши, що ви не заповнили цю адресу або пам'ять навколо неї, перевіряйте інформацію бухгалтерського обліку безпосередньо перед нею. Графічно це буде так:
____ The allocated block ____
/ \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
^
|
+-- The address you are given
Пам’ятайте, що розмір заголовка та підкладки повністю визначено реалізацією (насправді вся справа визначена реалізацією (а), але параметр обліку в рядку є загальним).
Контрольні суми та спеціальні маркери, які існують у бухгалтерській інформації, часто є причиною помилок, таких як "Арена пам'яті пошкоджена" або "Подвійне вільне", якщо ви їх перезаписуєте чи звільняєте двічі.
Прокладка (щоб зробити розподіл більш ефективним) - це те, чому ви можете іноді написати трохи пізніше кінця потрібного простору, не викликаючи проблем (все-таки, не робіть цього, це невизначена поведінка і, просто тому, що це працює іноді, не є т. значить, це нормально робити).
(a) Я написав реалізацію malloc
вбудованих систем, де ви отримали 128 байт незалежно від того, що ви просили (це був розмір найбільшої структури в системі), припускаючи, що ви просили 128 байт чи менше (запитів на більше повинні відповідати NULL значенням повернення). Дуже проста бітова маска (тобто не в рядку) була використана для того, щоб вирішити, виділяється чи 128-байтний фрагмент.
Інші, які я розробив, мали різні пули для 16-байтних фрагментів, 64-байтових, 256-байтних та 1К-фрагментів, знову використовуючи бітову маску, щоб визначити, які блоки використовуються чи доступні.
Обидва ці варіанти зуміли зменшити накладні дані бухгалтерської інформації та збільшити швидкість malloc
та free
(не потрібно з’єднувати сусідні блоки при звільненні), що особливо важливо для середовища, в якому ми працювали.