Avatar billede tipsen Nybegynder
24. januar 2002 - 15:29 Der er 18 kommentarer og
3 løsninger

Deallokering af lokale variable i ansi c

Jeg har følgende programstruktur i ansi c:

Globale variabelerklæringer

main() {
  Kald underrutine1();
  Kald underrutine2();
  ...
}

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;
}

ErrorRutine() {
  Giv relevant fejlmelding til brugeren;
  Free globale variable;
  Exit program;
}

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?

Mvh

Tommy
Avatar billede chries Nybegynder
24. januar 2002 - 15:33 #1
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;
}
Avatar billede jpk Nybegynder
24. januar 2002 - 15:37 #2
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...

case 2:
// Delete vars in anothe way...
Avatar billede chries Nybegynder
24. januar 2002 - 15:37 #3
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.
Avatar billede jpk Nybegynder
24. januar 2002 - 15:41 #4
chries:
Nå, men så er der jo ikke længere nogen grund til at bekymre sig om memory-deallokering...
Avatar billede chries Nybegynder
24. januar 2002 - 15:43 #5
Læste du ikke det jeg skrev ?
Avatar billede jpk Nybegynder
24. januar 2002 - 15:43 #6
chries:
memory-leaks bliver først frigivet ved genstart af OS...
Avatar billede chries Nybegynder
24. januar 2002 - 15:45 #7
vil du vædde ?
Avatar billede chries Nybegynder
24. januar 2002 - 15:54 #8
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.

void main()
{
    void *p;

    while(1)
    {
        p = new int;
    }
}
Avatar billede tipsen Nybegynder
24. januar 2002 - 15:54 #9
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?

/Tommy
Avatar billede chries Nybegynder
24. januar 2002 - 15:56 #10
hey, hvordan huggede jeg dit nick ?
Avatar billede jpk Nybegynder
24. januar 2002 - 16:13 #11
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.
Avatar billede kamikaze Nybegynder
24. januar 2002 - 18:26 #12
jpk:
Ja, det kan man godt i ansi C.
Avatar billede professoren Nybegynder
28. januar 2002 - 17:17 #13
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....
Avatar billede ricelius Nybegynder
28. januar 2002 - 17:28 #14
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
Avatar billede ricelius Nybegynder
28. januar 2002 - 17:29 #15
For resten hedder det NULL og ikke null...
Avatar billede chries Nybegynder
28. januar 2002 - 17:50 #16
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.



http://www.byte.com/documents/s=1778/byt20011107s0002/

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.
Avatar billede jpk Nybegynder
29. januar 2002 - 09:14 #17
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...
Avatar billede tipsen Nybegynder
21. februar 2002 - 22:56 #18
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!
Avatar billede jpk Nybegynder
22. februar 2002 - 00:01 #19
Ok, tak fordi du siger til.

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!
Avatar billede chries Nybegynder
22. februar 2002 - 09:14 #20
Svar
Avatar billede ricelius Nybegynder
22. februar 2002 - 17:58 #21
Dette er så et svar :).
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester