1 / 20

Microsoft.NET környezet

Microsoft.NET környezet. Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz. 1. Destructor. A konstruktor-ok a példány használata előtt hívódnak meg, a példány életciklusának elején. A destruktorok olyan speciális metódusok, amelyek

colm
Download Presentation

Microsoft.NET környezet

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Microsoft.NET környezet Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz 1

  2. Destructor • A konstruktor-ok a példány használata előtt hívódnak • meg, a példány életciklusának elején. • A destruktorok olyan speciális metódusok, amelyek • az életciklus végén hívódnak meg. • A destruktorokban a példány megszűnése előtti • ‘nagytakarítás’-t kell elvégezni: • pluszban foglalt memória felszabadítása • megnyitott file-ok lezárása • nyomtatás befejezésének jelzése • hálózati kapcsolatok lezárása • stb… 2

  3. Destructor A destruktorok neve kötelezően megegyezik az osztály nevével, de előtte egy ~ jel kell szerepeljen! class TFtpKliens { ~TFtpKliens() { // hálózati kapcsolatok lezárása ... } } A destruktornak nem lehet elérési szint módosítója (automatikusan public)! A destruktornak nem lehet paramétere sem! Ezért minden osztályhoz maximum 1 db destruktort készíthető! 3

  4. Explicit destructor hívás Miért ez a sok megkötés a destruktorra? (#1) Történelmileg a destruktort először a programozók hívták meg explicit módon, valami hasonló módon: TVerem v = new TVerem(); … // v példány használata free v ~TVerem(); ( ez egyébként nem működik C#-ban !!!! A destruktort hívásakor szabadítódott fel a példányhoz tartozó memóriaterület is. Ha a programozó ‘elfelejtette’ ezt meghívni, akkor a példány ottragadt a memóriában, és memóriaszivárgás (memory leak) keletkezett. Az ilyen program ha sokáig futott a memóriában, akkor elég sok idő után a teljes memóriát ilyen ‘beragadt’, haszontalan példányok foglalták el. 4

  5. Explicit destructor hívás • Tipikus hibák: • A programozó ‘elfelejti’ meghívni a felszabadítást. • Ekkor a példány ottragadt a memóriában, és memóriaszivárgás • (memory leak) keletkezett. Az ilyen program ha sokáig futott a • memóriában, akkor elég sok idő után a teljes memóriát ilyen • ‘beragadt’, haszontalan példányok foglalták el. • A programozó rosszkor (idő előtt) hívta meg a felszabadítást, a példányra még van hivatkozás. a = peldany; b = a; // b is ugyanarra a példányra mutat free a; // a példány eltűnik a memóriából b.muvelet(); // ez itt hiba forrása már Ekkor a program ‘bármit’ is csinálhat… de jót ritkán 

  6. Referenciaszámlálás elve • (#2) Erre megoldást nyújtott a referencia típusú változó: • Ennek során a futtató rendszer nyilvántartotta • nemcsak azt, hogy hol vannak a példányok számára • lefoglalt memóriaterületek, hanem azt is, hogy • hány változó hivatkozik az adott példányra. • ( referenciaszámlálás elve ) • Amikor egy példány memóriaterületét egy változóba • értékül adjuk, akkor a referenciaszámláló növelődik • 1-el. • Amikor egy ilyen változó másik értéket kap, vagy • megszűnik, akkor a referenciaszámláló csökken 1-el. • Amikor egy példányhoz tartozó referenciaszámláló • eléri a 0-t, akkor automatikusan fel lehet szabadítani • a hozzá tartozó memóriaterületet. 6

  7. Referenciaszámlálás elve public int Akarmi() { TVerem v = new TVerem(); // v használata ... } Példány memória allokálása Referenciaszámláló = 1 A lokális ‘v’ változó megszűnik létezni Referenciaszámláló = 0 Példány törlése a memóriából automatikusan! A példány törlése során 1: meg kell hívni a destruktorát, hogy ‘éretsítődjön’ a példány, hogy törlése fog kerülni, amit még akar az ‘utolsó szó jogán’ azt tegye meg 2: a lefoglalt memória felszabadítása 7

  8. Referenciaszámlálás elve Az ilyen referenciaszámlálás-elvű programozási nyelveken a destruktort már nem explicit módon hívja meg a programozó, hanem a futtató rendszer hívja meg automatikusan (implicit). A futtató rendszer viszont nem fog neki paramétert átadni (nem is tudna honnan), ezért itt már nincs értelme a destruktort paraméteresen megírni (nem is szabad). 8

  9. Referenciaszámlálás elve A referenciaszámlálás nem okoz komolyabb mérvű lassulást a program futása során! Ugyanakkor a programozók azonnal megszerették, mert megszűnt a memóriaszivárgás, egyszerűsödött a program írása, egy hibalehetőség megszűnt (egy gonddal kevesebb). Ugyanakkor jegyezzük meg, hogy a referenciaszámlálás bonyolultabb esetben sajnos egyszerűen semmit sem ér  ! 9

  10. Referenciaszámlálás halála Tegyük fel, hogy egy A példány hivatkozik egy B példányra, és a B is hivatkozik az A példányra ( kölcsönös hivatkozás ). Ilyenek pl. a ciklikusan láncolt lista elemei! Referenciaszámláló = 2 változó = ”A” példány; ”A” példány ”B” példány Referenciaszámláló = 1 10

  11. Referenciaszámlálás halála Ha a változó megszűnik, vagy már nem erre a példányra hivatkozik, akkor az ”A” példány a programból már elérhetetlenné vált. Ugyanakkor a referenciaszámlálója még mindig 1! Referenciaszámláló = 1 változó = null; ”A” példány ”B” példány Referenciaszámláló = 1 Ekkor az ”A” és a ”B” példány is beragadt a memóriában! Pedig ezt akartuk kikerülni… 11

  12. Garbage Collector felemelkedése (#3) Egy komolyabb programban a példányok egymásra is hivatkoznak, és ez egy komoly hivatkozási hálót ( gráfot ) hoz létre. Egy egyszerű referencia számlálás kevés a felesleges példányok felfedezésére és kiszűrésére. a program ‘élő’ változói hivatkoznak a példányokra 12

  13. Garbage Collector A megoldás, hogy a gráfot be kell járni (gráfbejáró algoritmussal, pl szélességi vagy mélységi bejárás) a program változóiból kiindulva. Amely példányhoz nem lehet eljutni az élek ( hivatkozások ) mentén, azok a példányok feleslegesek, és ki lehet őket törölni. Ezt a megvalósítást már nem referencia-számlálásnak nevezzük, hanem ‘szemétgyüjtésnek’. Szemét = garbage Gyűjtő = collector 13

  14. Garbage Collector Amikor új példányt hozunk létre, akkor egy halom (heap) területen lefoglalunk egy egybefüggő szakaszt. Ezen területen az első szabad helyet egy változó jelöli, őt kell növelni a lefoglalandó terület méretével: Obj1 NextObjPtr

  15. Obj4 Obj3 Garbage Collector Aztán jön a GC, elemzi a hivatkozási gráfot, és kiszúrja a felesleges példányokat. A gyökerek a program aktuálisan élő változói: NextObjPtr 1. Gyökerek 2. Elérhetőségi gráf Gyökerek 3. Takarítás Obj2 4. Tömörítés Obj1 5. Mutatók frissítése

  16. Garbage Collector Ha a futtató rendszer GC-t használ, akkor a destruktort hívása automatikusan történik meg, amikor eljut odáig a GC. Ez általában nem azonnal történik meg, mint ahogy a példány ‘szemétté’ válik, időre van szükség. Ezért a destruktort hívásának időpontja nemdeterminisztikus. Az sem determinisztikus, hogy az ”A” vagy a ”B” példányra hívódik-e meg először a destruktor, és szabadítódik fel a memória. ”A” példány ”B” példány 16

  17. Garbage Collector C#-ban a destruktort a programunkkal párhuzamosan, egy külön szálon fut. Másodpercenként több száz millió példányt képes felfedezni, és felszabadítani ha kell. Valamelyest lassítja a program futását, de ez elhanyagolható azon előny mellett, hogy garantáltan nincs memóriaszivárgás a programban, és a programozó nem véthet ilyen jellegű hibát. Pl: egy GC-vel ellátott nyelven a láncolt lista minden elemének törlése: A többit a GC végzi  FejElem = null; 17

  18. Garbage Collector Nagyon ritkán írunk destruktort, mert: - a pluszban lefoglalt memória is példány, és a GC majd azt is fel fogja szabadítani - a hálózati kapcsolat létrehozásához is példányosítani kell egy ‘hálózati kapcsolat’ osztályt, és ezen példányt a GC meg fogja találni, és meghívja rá az ő destruktorát, és akkor a hálózati kapcsolat automatikusan lezárja magát stb… Ezért csak nagyon speciális esetben kell nekünk magunknak explicit módon felszabadítani erőforrást. 18

  19. Garbage Collector Valójában a C#-ban nincs is destruktor, csak destruktornak kinéző metódus. A destruktor szót egyéb OOP nyelvekből vette át a C#. A destruktort valójában a Finalize() metódus override-ja. class TSajat { ~TSajat() { ... } } class TSajat { protected override Finalize() { ... } } 19

  20. Garbage Collector A C# fordítóprogramja a destruktorunkat automatikusan Finalize()-nek olvassa. De nem engedi meg, hogy közvetlenül a Finalize-t definiáljuk felül. Ha az ős osztálynak is van destruktora, akkor az le fog futni, mielőtt a mi destruktorunk elindulna hasonlóan a konstruktorok hívási láncához. 20

More Related