underrutine1() { Lokale variabelerklæringer; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, kald ErrorRutine; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, kald ErrorRutine; ...; free lokale variable; }
underrutine2() { Lokale variabelerklæringer; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, kald ErrorRutine; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, kald ErrorRutine; ...; free lokale variable; }
Det "noget" som kan gå galt i underrutinerne kan være hukommelsesallokering, men også andre "ting".
Mit problem er, at der på nuværende tidspunkt ikke bliver ryddet op i de lokale variable, hvis "noget" går galt i en underrutine.
Slavemetoden til dette er følgende struktur i underrutinerne:
Hvis "noget" kikser { free(lokalvariabel1); free(lokalvariabel2); ... kald ErrorRutine; }
Da jeg måske kontroller 10 gange eller mere om noget er ved at gå galt i underrutinerne, vil det bare kræve ekstremt mange free() linier i alle underrutinerne. Derfor kunne jeg godt tænke mig en mere elegang løsning til dette.
Jeg har forsøgt, at lade ErrorRutine tage et valgfrit antal inputargumenter og parse pointere til de lokale variable og free'e dem i ErrorRutine. Det fungerer også, hvis jeg på forhånd ved hvilke variabeltyper der bliver parset, hvilket desværre ikke er tilfældet.
En anden idé jeg har leget med er at lave et array med pointere til de lokale variable samt information om variabeltypen og give en pointer til dette array som inputargument til ErrorRutine. Jeg ved ikke om dette er den vildeste høkerløsning og jeg er heller ikke helt sikker på, at jeg kan overskue at lave det...
Det er vigtigt, at en eventuel løsning ikke involverer metoder/funktioner som ikke er ansi c, da det er et krav, at programmet laves i dette!
Er der nogle der har idéer/forslag/løsninger til denne problemstilling, vil jeg være glad for at høre dem. Hvis min forklaring af problemet ikke lige er forståelig, vil jeg gerne sende udsnit af sourcekoden.
PS: Hvad sker der egentlig med hukommelsen der bruges til de lokale variable, når de ikke free'es af programmet - er det en "memoryleak" og er der forskel på en Windows og en Unix platform?
hvorfor sletter du dem ikke bare før du kalder exit ?
underrutine1() { Lokale variabelerklæringer; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, slet indtil nu oprettede lokale varsiable og kald ErrorRutine; Dynamisk hukommelsesallokering til lokal variabel; Hvis "noget" kikser, slet indtil nu oprettede lokale varsiable og kald ErrorRutine; ...; free lokale variable; }
Du kan selvfølgelig tilføje en parameter til din løsning med et antal pointere. Denne parameter skulle så angive hvorledes nedlæggelsen skulle ske. fx: case 1: // Delete vars in one way...
Hvis dit program er et normal win32 program med new og delete (free/malloc), rekviverer dit os alt det du har leaket når programmet afsluttes (ihvertfald i NT/2k/xp).
Problemet er når du kører, så sluger den langsom mere og mere hukommelse indtil der ikke er mere. Det beslaster dit OS meget da den ikke har de resource tilgængeligt dit program har slugt.
Det kommer an på hvad du allokerer (hukommelse område i dit OS), hvad du agér som i et OS og hvilket OS det er.
Hvis du kører dette program under w2k (har lige testet), den sluger hurtigt 250 MB. Dræber det med end task.. så kan du se at alt hukommelse rekvikeres tilbage til available memory.
chries: Det med at free'e de lokale variable inden jeg kalder exit, er også det jeg har angivet som slaveløsningen - grunden til at jeg ikke er så begejstret for denne er, at der kan komme 50-100 free(...)-linier i hver underrutine - dette gør, at det bliver sværere at overskue rutinerne!
jpk: Er det nok også at angive antal pointere? Hvad nu hvis jeg vil slette forskellige typer som eks. (double*, int*, double*) el. (char*, double*, int*) - For at det fungerer med at sige, at der er 3 pointere kræver det vel, at hver pointer fylder det samme? - jeg ved ikke om en pointer til en char fylder det samme som en pointer til en double!?
Da programmet kommer til at bruge _meget_ hukommelse, skal jeg helt sikkert rydde op undervejs! Desuden skal programmet også kunne køre på unix - jeg ved ikke om den også selv rydder op efter programmet?
NB: Hvis jeg skal bruge meget hukommelse, skal jeg så benytte far_alloc og far_free? (jeg kan ikke huske om det er de korrekte navne) - og er det platformafhængigt?
chries: Jeg kender udmærket det lille eksempel, men jeg mener dog ikke der er nogen garanti herfor! Hvis du kan finde noget dokumentation, er jeg meget interesseret i at få det opklaret!
tipsen: Du kunne måske bare lave en struct (kan man det i ansi c?) der indeholder alle de pointers du skal bruge. Du kan så give funktionen en pointer med til denne struct, som så sletter den memory du har taget.
problemet opstår hvis du har brugt de samme variablenavn i global samt lokale variabler! Hvis du ikke brug de samme navn, har compileren letter at finde ude af, hvilken variable er lokal/global. Problemet er løst i c++, fordi local variables gå ude af "scope" når løkken forlades....
En double*, int*, char*, long* etc. fylder det samme (i hvert tilfælde under 32-bit Windows). Til gengæld fylder double, int, char, long ikke det samme. I stedet for double*, char* etc. kan du bruge void*. Fx char *charpointer = malloc(1024); void *voidpointer = charpointer; // adressen kopieres, ikke værdien free(voidpointer); charpointer = voidpointer = null; // streng taget ikke nødvendigt
tipsen: Kunne godt tænke mig at vide hvordan du får det fusket hen, når du har fundet en passende løsning :-)
ved ikke om "atexit" kunne bruges til noget. Den kalder en funktion før du lukker ned (også ved exit)
jpk:
Du har nok ret i det kommer an på hvad man allokere. Hvis det er objekter der kan eksistere efter en applikation stopper, ville det nok ikke blive slettet af OS'et (kan ikke komme i tanke om hvad det skulle være, men der er sikkert nok der kan). Der er temmelig få oplysninger på nettet (eller jeg søger efter det forkerte :-) ) http://classes.csumb.edu/CST/CST337-01/world/os_introduction/operating_systems_introduction.htm
Memory Manager = controls the Main Memory. Checks address validity for each request made to memory. If storage is requested, the manager must find memory not currently in use and allocate it for this request. The manager must keep track of each application/user and what memory they are using (place in a table). Also, when applications exit, the manager must reclaim/deallocate the memory the application was using.
The OS Must Protect Itself No action of a nonsuper-user process can crash the OS: no sequence of instructions, no system call, no application error. The operating system must protect itself from user actions whether they are accidental or malicious. Time does not crash the operating system. The operating system must not leak resources, and it must recover all resources when processes terminate whether intentionally or unintentionally.
chries: Jeg har ladet mig fortælle at windows handles ikke nødvendigvis frigives automatisk. Om det er en fact ved jeg ikke, men at det sker kender vi vist alle Windows godt nok til at tro...
ricelius, chries og jpk: Gider i smide et svar - jeg har kunnet anvende dele af jeres svar og samlet set fået en ok løsning!
-mine egne funktioner er pt. lidt grimme, da de laver en del forskelligt arbejde, men senere kan det være jeg lige smider løsningen her i en pæn og overskuelig version!
Mit bedste bud er stadig at indkapsle dine variable i en struct, således du kun behøver ét argument. Jeg glæder mig dog til at høre hvad du er kommet frem til!
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.