Візуальне програмування і mfc - управління пам'яттю

Перш ніж вивчати управління пам'яттю в Windows, треба спочатку розібратися в тому, що таке процес (process). Програма ґ це ЕХЕ-файл, який можна запустити з Windows різними способами. Після запуску програма стає процесом. У процесу є своя пам'ять, дескриптори файлів та інші системні ресурси. Якщо двічі поспіль запустити одну і ту ж програму, то виходить два окремих процесу.

пристрій пам'яті

  • образ ЕХЕ-файлу програми;
  • все несистемні DLL, завантажені Вашою програмою (включаючи DLL-модулі MFC),
  • глобальні дані програми (доступні як з читання та запису, так і тільки з читання);
  • стек програми;
  • динамічно виділяється пам'ять, в тому числі купи Windows і бібліотеки З періоду виконання;
  • файли, спроектовані в пам'ять;
  • блоки пам'яті, спільно що використовуються декількома процесами;
  • пам'ять, локальна для даного виконуваного потоку;
  • особливі системні блоки пам'яті, в тому числі таблиці віртуальної пам'яті;
  • ядро і DLL-компоненти Windows.

Як вус троена віртуальна пам'ять

Момент читання і запису сторінки (щоб досягти максимальної продуктивності) визначає диспетчер віртуальної пам'яті Windows. Якщо якийсь процес не використовував сторінку протягом певного періоду і ця пам'ять потрібна іншому процесу, дана сторінка вивантажується з пам'яті, а замість неї завантажується сторінка нового процесу.

Всі процеси спільно використовують один великий загальносистемний файл підкачки (swap file), в який поміщаються (при необхідності) всі види даних "для читання і запису" і деякі види даних "тільки для читання". (Windows NT підтримує одночасну роботу з декількома файлами підкачки.) Windows визначає розмір файлу підкачки в залежності від розміру ОЗУ і вільного дискового простору, але існують способи тонкої настройки розміру і матеріального становища цього файлу.

Функція VirtualAlloc: передана і зарезервована пам'ять

Якщо програмі потрібна динамічно розподіляється пам'ять, то рано чи пізно їй доведеться викликати функцію VirtualAlloc. Швидше за все викличете її не програміст, а функції Windows або бібліотеки З періоду виконання, виділяють пам'ять з купи. Знаючи, як працює VirtuаlAlloc, можна краще зрозуміти функції, які звертаються до неї.

Функції управ ління пам'яттю

Купа Wind ows і сімейство функцій GlobalAlloc

Купа (heap) ґ це пул пам'яті будь-якого процесу. Коли програмі потрібно блок пам'яті, онавизивает функцію, що виділяє пам'ять з купи, а щоб звільнити раніше виділену пам'ять, ґ функцію, парну першої. Вирівнювання по межах, кратним 4 КБ, в цьому випадку не проводиться; диспетчер купи використовує простір на виділених раніше сторінках або звертається до VirtualAlloc. щоб отримати додаткові сторінки. Одна з двох куп, з якими програма працює, ґ купа Windows. Для виділення з неї пам'яті служить функція HeapAlloc. а для звільнення ґ функція HeapFree. HeapAlloc особливо зручна для виділення "великих" блоків пам'яті.

Купа бібліотеки З періоду виконання, _heapmin і С ++ - оператори new і delete

Однак, купа Windows (і функція HeapAlloc) Ї це не та купа, з якої додаток будете працювати найчастіше. Існує ще одна купа ґ нею керує бібліотека З періоду виконання (С RunTime library, CRT). Доступ до CRT-купі реалізується функціями malloc і free, безпосередньо викликаються операторами C ++ new і delete. Ця купа оптимізована для виділення блоків малого розміру.

Звичайно, функція malloc викликає VirtualAlloc, але робить це дуже хитро. При першому виклику вона резервує регіон розміром 1 Мб (в майбутніх версіях Visual C ++ ці значення можуть бути змінені) і передає блок пам'яті, розмір якого кратний 64 Кб (якщо malloc викликаний щоб виділити пам'ять розміром 64 Кб або менше, виділяється один 64-кілобайтний блок. При наступних викликах пам'ять виділяється по можливості з цього блоку; в іншому випадку диспетчер купи викликає VirtualAlloc. щоб передати додаткову пам'ять. Після того, як весь регіон розміром 1 Мб витрачений, malloc резервує ще один регіон розмір 2 Мб, потім інший, але вже размеро 4 Мб і т.д. передаючи пам'ять в міру необхідності.

Якщо процес виділив багато пам'яті з CRT-купи, а потім звільнив більшу частину цієї пам'яті, всі сторінки залишаються переданими. Хоча оперативна пам'ять при цьому може бути і не виділена, процес займає сторінки в файлі підкачки, які залишаються недоступними іншим процесам. При виклику іншої CRT-функції, _heapmin. диспетчер купи повертає всі вільні сторінки і, більш того, звільняє будь-які, повністю повернуті регіони.

Відображені в пам'ять файли і колективна пам'ять

Файлове відображення можна створити за допомогою функції CreateFileMapping. Для відкриття існуючого відображення з певним ім'ям програми можуть використовувати функцію OpenFileMapping. Функція MapViewOfFile відображає частину файлу в блок віртуальної пам'яті.

Особливістю відображаються в пам'ять файлів є їх спільне використання різними додатками, тобто якщо два додатки відкрили файлове відображення з одним і тим же ім'ям, то вони, по суті, створили блок розділяється пам'яті.

Не зайве використовувати дисковий файл, якщо необхідно лише передати кілька байт між додатками? Насправді немає необхідності явно відкривати і використовувати дисковий файл для отримання відображення в пам'яті. Додатки можуть передати спеціальне значення дескриптора 0хFFFFFFFF в функцію CreateFileMapping для отримання відображення безпосередньо в системний сторінковий файл. Це, по суті, створює блок розділяється пам'яті.

Неско тілько рад по роботі з динамічною пам'яттю

Чим інтенсивніше використовується купа, тим в більшій мірі вона фрагментируется і тим повільніше працює програма. Якщо передбачається, що час безперервного функціонування програми буде обчислюватися годинами або днями, то слід проявити обережність. Краще виділити всю необхідну пам'ять при запуску програми і звільнити її при закритті, але це не завжди можливо. Тут може перешкодити клас CString, який постійно виділяє і звільняє крихітні порції пам'яті. Однак розробники MFC недавно внесли в нього ряд поліпшень.

Якщо програма в основному виділяє блоки малого розміру, але зрідка вимагає 6ольшіх блоків (займаючи їх на час, відмінне від того, на яке вона займає малі блоки), тоді варто подумати про виділення великих блоків функцією HeapAlloc. а не new. Це дещо зменшить ступінь фрагментированности CRT-купи. Не слід забувати час від часу вьзивать _heapmin. Варто ретельно стежити за тим, як був отриманий той чи інший блок пам'яті Ї додатка не минути серйозних проблем, якщо воно, наприклад, викличе HeapFree для покажчика, отриманого за допомогою new.

Слід врахувати, що розмір стека може бути таким, як треба. Так як тепер немає обмеження в 64 Кб, в стек можна поміщати об'єкти великого розміру, що зменшує необхідність у розподілі пам'яті з купи.

Схожі статті