Podoski Peter wrote:
Nyilván, de addig is meg kellene találnom, hogy hol nincs meghívva. Nem azt mondom, hogy a referencia számlálás azt oldaná meg, hogy ne kelljen meghívni. A referencia számlálás azt oldaná meg, hogy megtaláljam, mire nincs meghívva.Helló! Köszi a részletes leírást, így már világosabb a helyzet. Továbbra is mindenkit óva intenék ilyen jellegű problémára .NET-es referencia számláló implementációtól. A Control-okra bizony hívogatni kell a Dispose()-t, amennyiben jelentős mennyiségű erőforrást foglaltál le bennük. (Egyáltalán, minden IDisposable-re illik Dispose()-t mondani, amikor már nem használod, lásd "using" blokkok, mint burkolt try-catch-finally automatikus diszpozáló nyelvi elem).
Nem triviális controllunkban kellően sok hiba van ahhoz, hogy ez ne történjen meg (mármint, hogy a GC ne tudja automatikusan felszabadítani a hibásat).A Controls.Clear() nagyjából ugyanazt csinálja mint egy ArrayList.Clear() - mivel ő egy ArrayList-et használ belül (amellett, hogy az IList-et implementálja), gyakorlatilag tényleg csak egy listából tűnik el a referenciád. Ha csak ennyit "takarítasz", akkor ugyan már nincs referenciád a programodon belül a Control-ra, viszont egy Win32 Handle rajta van a Controlon (ami a form Handle-je is). Így a TableLayout-ba pakolt Control-ok Dispose() hívás nélkül a TableLayout szülő formjának megszűnéséig élni fognak, a GC nem fogja őket halottnak nyilvánítani. Ha Dispose()-t hívsz rájuk, akkor szemétté alakulnak (valószínűleg nem szabadulnak fel). Az egy teljesen más kérdés, hogy miért nem csökken a program feladatkezelőben is látható memóriahasználata. Amikor a GC takarít, akkor igazából csak összegyűjti a szemetet (megjelöli őket), igazi kidobás csak memóriafoglaláskor történik - by design. Készítettem egy példaprogramot, amiben egy olyan UserControl volt, aki 50 megás tömböt foglalt le születése után (és használta is). Beraktam 20 darabot a TableLayoutPanel-be, majd Dispose() hívás után kivettem őket, és ezt megismételtem jó sokszor, közben nézve és kiíratva a formra a memóriahasználatot. A helyzet az, hogy a GC elég okos ahhoz, hogy eldöntse, hogy mit műveljen a memóriával, nagyon nem kell aggódni miatta (a programozó az értékes idejét inkább az üzleti logika implementálása fordíthatja - ez az elsődleges "aspektus").
Nagyszerű, mi 1,5G-nál járunk, de ez engem nem érdekelne annyira (később ki kellene amúgy is optimalizálni a kódot és folyamatban is van az újraírása). Ami zavar, hogy elfogy a window handle.Nem ismeretlen számomra a C++-os memóriakezelés szabadsága, de itt egyszerűen nem kell megijedni, hogyha a 200 megányi tényleges memóriahasználat a feladatkezelőben 800 megának látszik, majd újabb 50 foglalásakor 500 lesz, és újabb 50 mega foglalásakor 300, és a Dispose() után is marad 300.
Ez nem a csak a keretrendszerre utalt, hanem arra, hogy a keretrendszer milyen szemléletet ültet a programozókba. Mivel a legtöbb helyen nem kell a memória felszabadítással foglalkozni, programozóink ott se gondoltak arra, hogy kellhet, ahol kivételesen kellett volna (és ezért nem is teljesen hibáztathatók). Ha már azt mondta a rendszer, hogy nem kell felszabadítani, ebben az esetben is megcsinálhatta volna eszerint a filozófia szerint.Még egy dologra regálnék: "(Ennyit arról, hogy majd a nyelv valamit megcsinál a programozó helyett.)"
Nem fogok példaprogramot adni, mert ha redukálom már nem fog szivárogni, az éles kódot pedig nyilván nem kaphatja meg senki. Bár lehet, hogy majd megpróbálok demonstrációs kódot írni.Dispose()-t neked kell hívni a Control-ra, minden mást megold a keretrendszer. Ha mégis memory leaked van, akkor bizonyára a kódban van a hiba, és ezt addig fent is tartom, ameddig nem tudsz mutatni egy olyan mintaprogramot, ami ténylegesen leakel, pedig rendeltetésszerűen van diszpozálva benne mindenki. (nem kell éles projektből részlet, ki lehet emelni belőle a lényeget)
Ezt mint mondtam még profiler eszközzel is ki tudom deríteni (és nem szivárog - a szó klasszikus értelmében -, mert pont az a baj, hogy a szemétgyűjtő nem hajlandó valamiért összeszedni), épp csak nem tudom meghatározni, mely objektumok vannak még legálisan a memóriában és melyekre nincs már referenciánk és mégis ott vannak (tehát disposolnunk kellett volna). És hogy ne legyen triviális egy naptár modulról van szó, amely többszáz napot és a megfelelő adatait tartja a memóriában (úgy kb 300 ezer objektum péládonyonként). Azt hiszem ilyen nagyságrendben azért nem működik az egyesével megvizsgálom, "te élsz még?" megközelítés.(Az aktuális memóriahasználtot a GC.GetTotalMemory(false) hívással tudod kideríteni - de ezt biztos ismered.)
H. -- Az eletben vannak szabalyok Nehanyat meg lehet kerulni, a tobbit pedig meg lehet szegni (The Matrix) -----BEGIN PGP PUBLIC KEY BLOCK----- Version: OpenKeyServer v1.2 Comment: Extracted from belgium.keyserver.net mQGiBEE/HTYRBACInacMGc8B/lkX3CXh5D9wUDlmza4hoatNZjJmWNnPWC9c0h2V Pi9zYJ1bVqeUnNDzCRpovPdwrswWvb9WpVOS0A7TafzWxCYud6gN8g5KiC7cSuJV cxI0uv3jWSjUkLnECqTpm9piM4WptXrdFLxUyrKPu+Nl82QSjfdbB+8xXwCg+rWO KeOZZGGGIYWu+rZ0M/MqyCUD/jqQVc7alF8+5y//zNDml3THTc3ljK8CLcHxFv6F uADmvHSePRTR1ACBV3dTxL8awvanRsXC25LOuYgM1hF9RRwof59xNtXVttvo724b FDR+oRDVKyoEm6Istfn9xbbNqRqPfk83SHvect/hlHsfgaTBKd+IRAEkbMIdRin/ E45fA/0bzklqLGj4a8qSxMMvZ1Ib+2RmH5I6o9o33FY3Nmc7IEXJizyTyQaASYCx ldjuRmfWSOP3gQRrH5owuZq5KBCC/PNMNnUsA4noFmvIilA/9UYqMtQ0BNr+miIM 9/LV70ZbBHVpDLjb2baMjbKrmCFf9rjlc17fFsWk5ZJuE3/UxLQrWmltbGVyIEF0 dGlsYSBUYW3DoXMgPGhpamFzenVAaGxmc2xpbnV4Lmh1PohXBBMRAgAXBQJBPx02 BQsHCgMEAxUDAgMWAgECF4AACgkQ+3OFVYni0PSysACffD6VDtoer3aBe8Gpvn8e gwiNNH8AmwcmBIrZeCOeobIuZZp3CCOgQblIuQENBEE/HTkQBACKNzv7gS0fgeiO AMoss2bbO7X9GuO3ufc3+zx2yGV7SvYAuyWLOSMhs1ZYBVp6IawDY88zEx81oxRj Jd4zO8h/3BI9cmjZ4NAmdv7lWjTs0I0ijFnemcFQaffxN8vIB9DqA4oyJ0A/bS7J 0E/i13sr7hRgB6NZbpy4PSSkczggvwADBQP8D3eakqeJHf1yLmw1XmQVDxHLxtrI VL0TShFEfMGU/MLfKpcmrd43EsSondsNNm8jv4b9Y/Wgc8XPQQrfPodC5mKt8mQC F/ovWBFs46YvhS5pojQmp6i9octTWw2OqVn3QgrBFqm4QvayLE9wRLm/xgaFApVI 4RiOOEA6SidURGCIRgQYEQIABgUCQT8dOQAKCRD7c4VVieLQ9HoZAJ4xR5Y1qlnC LTn1GkbEW0Va+72EqwCfQTP37ylZGrvpYnFoewBIMuLFHM8= =K0/l -----END PGP PUBLIC KEY BLOCK-----