Изменения

Перейти к: навигация, поиск

Работа с памятью

2648 байт добавлено, 22:31, 23 июля 2011
Куча
===Куча===
Рассмотрим теперь пример использования памяти: попробуем представить себе как можно реализовать динамически расширяющийся массив (вектор). Нас будет интересовать операция расширения массива: предположим, массив уже занимает какую-то непрерывную область виртуального адресного пространства (под его данные было выделено несколько страниц виртуального адресного пространства). Мы хотим расширить этот массив, увеличив его размер вдвое, скопировать в новый массив старые данные. После чего старый массив нам становится не нужен. Тут возникают два вопроса: какие страницы резервировать и что делать со старыми страницами. Заметим, что резервирование новых страниц и сопоставление им физической памяти -- дорогое удовольствие. Понятно, что у нас может возникнуть необходимость выделить еще какие-то данные и старые выделенные страницы памяти могут нам пригодиться -- используя их мы сможем записать новые данные, не выделяя новые страницы. Также заметим, что нам нужно бережнее относиться к остаткам страницы (когда мы записываем данные, занимающие страницу не полностью) -- нужно помнить про свободные куски используемых страниц. Вообще, сущность, манипулирующая страницами для эффективной работы с памятью, называется кучей.
Память можно выделять и освобождать напрямую через системные функции <tex>VirtualAlloc</tex> и <tex>VirtualFree</tex>. Вызывая <tex>VirtualAlloc</tex>, указывая размер блока памяти и желаемый атрибут доступа (обычно: чтение-запись). Система выделяет от свободной памяти блок. Теперь в программе выделена память, и есть указатель на нее. Когда память надо освободить - вызывайте <tex>VirtualFree</tex>. Система переведёт память обратно в свободную. Но как говорилось ранее с памятью нужно работать эффективно, поэтому существует куча, которая манипулирует страницами для эффективной работы с памятью. Хорошая новость заключается в том, что работа с кучей реализована на уровне ОС и вам можно не реализовывать ее самостоятельно.  В стандартной библиотеке , пришедшей из языка C также , <tex>libc</tex> реализованы функции <tex>malloc()</tex> и <tex>free()</tex>, соответственно для выделения и освобождения памяти. В самом C++ есть аналогичные функции для работы с кучей -- <tex>new (new[])</tex> и <tex>delete(delete[])</tex>. Для каждого <tex>malloc/new/new[]</tex> должны вызываться <tex>free/delete/delete[]</tex>, т.к. память сама не освобождается при выходе из функций. Не вызвав эти функции, reallocкуча останется неосвобожденнной, freeи произойдут утечки памяти.  Рассмотрим процесс выделения памяти в куче на примере простой программы: [[Файл:vmmap_before.png|right|thumb|200px|Память не выделена]][[Файл:vmmap_after.png||right|thumb|200px|Выделена память под массив]][[Файл:vmmap_delete. В C++ работа с кучей идет через операторы png||right|thumb|200px|Память освобождена]]  int main() { int *a = new int [1000000]; delete [] a; return 0; } До выполнения int *a = new int [1000000];куча в адресном пространстве программы занимает <tex>1152kB</tex>, а после выполнения команды - <tex>5060kB</tex>. Значит, память была выделена именно в куче, и объем выделенной памяти равен <tex>3908kB</tex>, что почти в точности соответствует объему массива <tex>int</tex> из <tex>1000000</tex> элементов при выделении <tex>4B</tex> на элемент.  После выполнения delete[] a;размер кучи снова равен <tex>1152kB</tex>, как и до выделение памяти под массив.
{{TODO| t=Переписать раздел про кучу подробнее и понятнее. Идея в том, чтобы сначала показать, что можно делать для эффективного распределения памяти, а потом обрадовать людей тем, что куча уже реализована.}}
69
правок

Навигация