Это явление, при котором память, выделенная в куче, разбивается на мелкие фрагменты, что может затруднить эффективное использование памяти и привести к снижению производительности. Фрагментация кучи бывает двух типов: внутренняя и внешняя.
Возникает, когда выделенный блок памяти больше, чем требуемый для хранения данных. Примеры: если система выделяет память блоками фиксированного размера (например, 8 байт), и программа запрашивает 5 байт, то оставшиеся 3 байта не будут использованы.
Возникает, когда свободная память разбивается на множество мелких блоков, и становится невозможно выделить большой непрерывный блок памяти, даже если суммарно свободной памяти достаточно. Примеры: программа многократно выделяет и освобождает память разного размера, оставляя после себя небольшие свободные участки.
Если память выделяется блоками разного размера, это увеличивает вероятность фрагментации.
Если одни блоки памяти используются долго, а другие освобождаются быстро, это приводит к появлению «дыр» в куче.
Фрагментация может замедлить работу программы, так как аллокатор памяти тратит больше времени на поиск подходящих блоков.
Неправильное управление памятью может усугубить фрагментацию и привести к утечкам.
First-fit, Best-fit, Worst-fit: Разные стратегии поиска свободных блоков могут влиять на степень фрагментации. Buddy System: Система управления памятью, где память делится на блоки размера, кратного степени двойки, что помогает уменьшить фрагментацию.
Перемещение данных в памяти для создания больших непрерывных блоков свободной памяти. Этот метод требует наличия сборщика мусора и поддержки перемещения объектов.
Выделение больших блоков памяти и управление ими внутри программы для уменьшения фрагментации. Это полезно для частых операций выделения и освобождения памяти однотипных объектов.
std::vector, std::list, std::unique_ptr, std::shared_ptr и другие контейнеры и умные указатели из стандартной библиотеки помогают управлять памятью более эффективно.
#include <iostream>
#include <vector>
class MemoryPool {
public:
MemoryPool(size_t size) {
pool.resize(size);
}
void* allocate(size_t size) {
if (currentOffset + size > pool.size()) {
throw std::bad_alloc();
}
void* ptr = pool.data() + currentOffset;
currentOffset += size;
return ptr;
}
void deallocateAll() {
currentOffset = 0;
}
private:
std::vector<char> pool;
size_t currentOffset = 0;
};
int main() {
MemoryPool pool(1024); // Пул памяти размером 1024 байта
int* p1 = static_cast<int*>(pool.allocate(sizeof(int)));
*p1 = 42;
double* p2 = static_cast<double*>(pool.allocate(sizeof(double)));
*p2 = 3.14;
std::cout << "p1: " << *p1 << ", p2: " << *p2 << std::endl;
pool.deallocateAll(); // Освобождение всех выделенных блоков
return 0;
}
Ставь 👍 и забирай 📚 Базу знаний