Cikk memória kezelése a Delphi 5

Memóriakezelés Delphi 5.0: Memory Manager

Ez a cikk leírja, hogyan kell használni a memória és a memória vezérlő a fő funkciók (nem tévesztendő össze a funkciókat, hogy működjön együtt a dinamikus memória). Úgy tűnik, hogy az anyag értelme a legtöbb későbbi változatai, de mégis, ha használja valami más, mint a Delphi 5.0, jó lenne megismerni a változtatások listáját.

A Delphi alkalmazás memória kezeli az összes dinamikus elosztás (költségvetési) és a szabad memóriát. Ezen keresztül a standard munkafolyamat Új, megsemmisíteni, GetMem, ReallocMem és FreeMem, valamint a memória kiosztás objektumok és hosszú sorok.

A memória manager kihegyezett alkalmazások által termel nagyszámú kis mennyiségű memória, amely jellemző OOP alkalmazásokhoz és feldolgozó lánc adatait. Más memóriakártyák vezetők (mint például a végrehajtását GlobalAlloc, LocalAlloc, valamint a támogatási ablakok halom (heap)) nem optimális az ilyen helyzetekben, és lelassíthatja az alkalmazást.

Az optimális teljesítmény érdekében a memória menedzser dolgozik közvetlenül a kernel virtuális memória Szelek (Win32 virtuális memória API) keresztül működik VirtualAlloc és VirtualFree. Fenntartott memória 1 MB buborékokat szakaszok és kiosztott blokkokban 16 Kb szükséges.

A memória menedzser irányítja a két változó, AllocMemCount és AllocMemSize tartalmazó blokkok száma kiosztott, és a teljes értékű a memóriát. Ezeket az adatokat fel lehet használni a kérelem hibakeresés.

A rendszer modul két eljárást, GetMemoryManager és SetMemoryManager, amelyeket fel lehet használni az alacsony szintű lehallgató hívást a memória vezérlő. Ugyanez modul egy olyan funkció GetHeapStatus, amely visszaadja a rekord tartalmazza a részletes információkat a memória állapotát vezetője.

Lefoglalt memória globális változó egy alkalmazás adat szegmensben megszűnik, amikor befejeződött. A helyi változók él a stack (verem). Minden alkalommal, amikor hívást egy eljárás vagy függvény, memóriát számukra, amely megjelent a kilépés az eljárás vagy függvény, bár a fordító optimalizálása lehet pusztítani őket hamarabb.

alkalmazás verem határozza meg a két érték: a minimális és maximális méretét. Ezek az értékek fordító irányelvek $ MINSTACKSIZE (alapértelmezett - 16 384 bájt) és a $ MAXSTACKSIZE (alapértelmezett - 1048576 bájt). A Windows hibát jelez, ha ez nem sikerül, ha az alkalmazás futtatásához, hogy megadja neki a minimális memória verem.

Ha az alkalmazás több verem helyet, mint amennyit a $ MINSTACKSIZE, amelyhez hozzá van rendelve blokkokban 4 Kb. Ha egy másik memória kiosztás letörik, vagy azért, mert a memória már nem, vagy azért, mert a teljes összeget a megkeresett verem meghaladta a $ maxStackSize kerül előállításra eksepshn: EstackOverflow egyébként veremtúlcsordulás vezérlés teljesen automatikus, az irányelv $ S, miután akadályozva kapcsolja ki, a bal csak a kompatibilitást a korábbi verziók.

Dinamikus változók által létrehozott új eljárások vagy GetMem, tetején helyeztük el és tároljuk azokat leölik a megsemmisíteni és FreeMem volt.

Hosszú sorok és széles vonalak (széles húrok), a dinamikus tömböket, variánsok és interfészek is elhelyezett egy halom, de a memória kiosztás irányító automatikusan szabályozott.

Leírása a változók és függvények

működnek AllocMem (Méret: Cardinal): Pointer;
Osztja ki a halom memória blokk előre meghatározott méretű. Minden byte memóriát nullára van állítva. Ahhoz, hogy a szabad memória használt FreeMem.

var AllocMemCount: integer;
Ez tartalmazza a szám a lefoglalt memória blokk. Ez a változó növekszik, valahányszor a felhasználó kéri egy új egységet, és csökken, ha a blokk felszabadul. Változó érték meghatározásához használt szám a „maradék” blokkokat.

Mivel a változó globális és él a rendszer egységet, annak közvetlen felhasználásra nem mindig biztonságos. A modulok statikusan, majd különböző esetekben AllocMemCount. Tekinthető statikusan linkelt alkalmazások, amelyek nem használja az idő futásidejű csomag (runtime csomag). Az alábbi táblázat összegzi információk felhasználása AllocMemCount típusától függően az alkalmazás.

Alkalmazások, amelyek nem használják csomagok és dll-és Delphi nyugodtan forduljon az ehhez a globális változó, mert nekik csak egy példányt belőle.

EXE csomagok nélkül dll

Az alkalmazások az csomagok és a dll-ki is lehet dolgozni nyugodtan AllocMemCount. Ebben az esetben az összes modul kapcsolódik dinamikus, és csak egy példány változó, mert csomagok, ellentétben dll, képes együttműködni a globális változók.

EXE statikusan linkelt dll

Ha a kérelmet és dll-ki használta őket statikusan vannak csatolva a futásidejű könyvtár (RTL), AllocMemCount soha nem szabad használni, amelyek közvetlenül és alkalmazást dll-ki lesz saját példányát. Ehelyett meg kell használni a GetAllocMemCount élő BorlandMM, amely visszaadja az érték a globális változó AllocMemCount bejelentette, BorlandMM. Ez a modul felelős a memória kiosztás minden modul szerepel a listán, amely az első megadott sharemem modult. A funkció az ebben a helyzetben, mert a globális változók bejelentett egy dll láthatatlan a másikra.

EXE csomagok és statikusan linkelt dll-kami

Nem ajánlott, hogy hozzanak létre vegyes használó alkalmazások és a csomagok és statikusan linkelt dll-ki. Ebben az esetben ügyelni kell arra, hogy működjön együtt dinamikusan memóriát, mint Minden modul tartalmazza a saját AllocMemCount. utal, hogy a lefoglalt memória, és felszabadítjuk ezt a modult.

var AllocMemSize: integer;
Ez tartalmazza a memória mennyisége bájtban összes memóriát lefoglalt blokkok alkalmazásával. Tény, hogy ez a változó jelzi, hogy hány byte memóriát által jelenleg használt alkalmazás. Mivel a változó globális, akkor érvényes mindenre mondta ellen AllocMemCount.

GetHeapStatus
működni GetHeapStatus: THeapStatus;
Visszaadja az aktuális állapotát a memória menedzser.

típus
THeapStatus = rekord
TotalAddrSpace: Cardinal; s
TotalUncommitted: Cardinal;
TotalCommitted: Cardinal;
TotalAllocated: Cardinal;
TotalFree: Cardinal;
FreeSmall: Cardinal;
FreeBig: Cardinal;
A fel nem használt: Cardinal;
Rezsi: Cardinal;
HeapErrorCode: Cardinal;
végén;

Ha az alkalmazás nem használja ShareMem modul, az adatokat a felvétel TheapStatus kapcsolódnak a globális halom (heap), egyébként is lehet adatokat megosztott memória különböző eljárásokkal.

Ez azt mutatja, hogy hány byte TotalAddrSpace nem a swap fájlt.

Ez azt mutatja, hogy hány byte TotalAddrSpace vannak csereállományból. Ennek megfelelően, TotalCommited + TotalUncommited = TotalAddrSpace

Hány bájt memóriát dinamikusan kiosztott a programot

Elérhető de fel nem használt memória (bájt) található, a „kis” blokkokat.

Elérhető de fel nem használt memória (bájt) található, a „nagy” blokkokat. Nagy blokkok képezhetők egy folytonos szekvencia „kis”.

Memória (bájtban) Soha ne adja ki (de elérhető) a program. A fel nem használt + FreeSmall + FreeBig = TotalFree.

Hogy mennyi memória (bájt) kell kupac menedzser szolgálni minden blokkot dinamikusan kiosztott a program.

A belső állapotát a kupac

Megjegyezzük, hogy TotalAddrSpace, TotalUncommitted és TotalCommitted utalnak OS lefoglalt memóriát a program működését, és TotalAllocated és TotalFree vannak kupacmemóriája használt memória dinamikus program által. Így nyomon követheti, hogy milyen a program által használt dinamikus memória használat és TotalAllocated TotalFree.

élni állandó HeapErrorCode MEMORY.INC (erősen ajánlott minden érdeklődő és haladó). A társaság és adunk nekik.

HeapErrorCode - értékei hibakódok

eljárás GetMemoryManager (var MemMgr: TMemoryManager);
Visszaad egy pointert az aktuális memória menedzser. TMemoryManager szerkezetét az alábbiakban ismertetjük.
TMemoryManager - adatstruktúra

típus
PMemoryManager = ^ TMemoryManager;

TMemoryManager = rekord
GetMem: funkció (Méret: Integer): Pointer;
FreeMem: funkció (P: Pointer): egész;
ReallocMem: funkció (P: Pointer; Méret: Egész szám): Pointer;
végén;

Ez a bejegyzés határozza meg, hogy mely funkciók használják kiosztani és a szabad memóriát.

GetMem funkciót kiosztani memória blokkot (méret nem lehet nulla), és visszatér a mutatót is. Ha ő nem tudja megtenni, akkor vissza kell hagyni.

ReallocMem funkciót perevydelit memória mérete a blokk P. Itt P nem lehet nulla, és mérete nem lehet 0 (bár a hívás ReallocMem nem a memória menedzser, elég elfogadható). A funkció azt kiosztani, amennyiben szükséges, a blokk új helyre, és visszatér a mutató erre a helyre. Ha a felosztás nem lehetséges, akkor vissza kell hagyni.

var HeapAllocFlags: Szó = 2;
Ezeket a zászlókat vezérli a memória vezérlő a memóriában. Ők lehet kombinálni, és a következő értékeket (alapértelmezett - GMEM_MOVEABLE):

Osztja fix memóriát. mert Operációs rendszer nem tudja mozgatni a blokkokat a memória, akkor nincs szükség, hogy blokkolja a memória (illetve nem kombinálható GMEM_MOVEABLE)

Osztja mozgatható memória. A Win32 blokkok nem lehet mozgatni, ha ezek található fizikai tárolás, de tudja mozgatni a kupac.

Memóriakiosztási (például működni GetMem) minden bájt memóriát fog kiállításra 0 (egy nagyszerű funkció)

Régen, hogy módosítsa a tulajdonságokat már kiosztott memória blokk

Bevezetett való kompatibilitás 16 bites verzió, de lehet használni, hogy optimalizálja a DDE műveleteket. Valójában, kivéve olyan ügyleteket, ezeket a jelzőket, és nem szabad használni

Pre felel GMEM_FIXED + GMEM_ZEROINIT

Pre felel GMEM_MOVEABLE + GMEM_ZEROINIT

funkció IsMemoryManagerSet: Boole;
TRUE értéket ad vissza, ha a valaki poherit Az alapértelmezett memória menedzser, és ragaszkodni ő helyette.

eljárás SetMemoryManager (const MemMgr: TMemoryManager);
Beállít egy új memória menedzser. Ez lesz a kiosztás során alkalmazott és felszabadítása eljárások GetMem, FreeMem, ReallocMem, Új és megsemmisíteni, valamint a konstruktőrök és a destruktor tárgyak és a munka a dinamikus húrok és tömbök.
SysFreeMem, SysGetMem, SysReallocMem
Íráskor használt saját memória menedzser. Egy másik értelemben nem találtam.

Hogyan írjunk memória menedzser

Gondolod, hogy ez nagyon nehéz? Természetesen nem. Itt egy példa segítségével rendszer maga Delphi: a vezérlő emlékezni fog az összeg a vérzés, mentességek és memória újraelosztását:

var
GetMemCount: integer;
FreeMemCount: integer;
ReallocMemCount: integer;
OldMemMgr: TMemoryManager;

működnek NewGetMem (Méret: Integer): Pointer;
kezdődik
Inc (GetMemCount);
Eredmény: = OldMemMgr.GetMem (méret);
végén;

működnek NewFreeMem (P: Pointer): egész;
kezdődik
Inc (FreeMemCount);
Eredmény: = OldMemMgr.FreeMem (P);
végén;

működnek NewReallocMem (P: Pointer; Méret: Egész szám): Pointer;
kezdődik

Inc (ReallocMemCount);
Eredmény: = OldMemMgr.ReallocMem (P, méret);
végén;

const
NewMemMgr: TMemoryManager = (
GetMem: NewGetMem;
FreeMem: NewFreeMem;
ReallocMem: NewReallocMem);

eljárás SetNewMemMgr;
kezdődik
GetMemoryManager (OldMemMgr);
SetMemoryManager (NewMemMgr);
végén;

Kapcsolódó cikkek