Professional Documents
Culture Documents
alocarea dinamică
laura.vasilescu@cs.pub.ro
Reminder Stivă (stack) vs Heap
Reminder Stivă (stack) vs Heap
Reminder Stivă (stack) vs Heap
• Variabile locale
Reminder Stivă (stack) vs Heap
• Variabile locale
• Variabile alocate
dinamic
Reminder Stivă (stack) vs Heap
• Variabile locale
• Variabile alocate
dinamic
• Variabile globale
Alocarea memoriei pe stivă
- recapitulare -
Exemplu didactic: procesor pe 4 biți
24-1
0
Exemplu didactic: procesor pe 4 biți
24-1
- Presupunem că tipul de
date halfbyte are și el 4
biți și e singurul care
există
0
Exemplu didactic: procesor pe 4 biți
0xF 14
0xE 8 Alocarea
0xD 14 variabilelor
0xC 4
0xB 11
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8; Alocarea
0xE 8
0xD 14 variabilelor
0xC 4
0xB 11
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
0xD 14 variabilelor
0xC 4
0xB 11
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b, 14 variabilelor
0xC d, 4
0xB 11 Ce valori au variabilele b și d?
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = ?
0xA 5 print(d) = ?
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 14 ; 0xE
0xA 5 print(d) = 4; 0x4
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 0xE
0xA 5 print(d) = 0x4
0x9 0
0x8 3
print(*b) = ?
0x7 13
0x6 5
print(*d) = ?
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 0xE
0xA 5 print(d) = 0x4
0x9 0
0x8 3
print(*b) = valoarea de la 14 = *0xE = 5
0x7 13
0x6 5
print(*d) = ?
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Alocarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 0xE
0xA 5 print(d) = 0x4
0x9 0
0x8 3
print(*b) = valoarea de la 14 = *0xE = 5
0x7 13
0x6 5
print(*d) = valoarea de la 4 = *0x4 =>
0x5 12 Segmentation Fault
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Modificarea
0xE c = 5
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 0xE
0xA 5 print(d) = 0x4
0x9 0
0x8 3
print(*b) = valoarea de la 14 = *0xE = 5
0x7 13
0x6 5
print(*d) = valoarea de la 4 = *0x4 =>
0x5 12 Segmentation Fault
0x4 0
0x3 4 *b = 10; ??
0x2 7 *d = 10; ??
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 14 variabilelor
0xC d = 4
0xB 11 print(b) = 0xE
0xA 5 print(d) = 0x4
0x9 0
0x8 3
print(*b) = valoarea de la 14 = *0xE = 5
0x7 13
0x6 5
print(*d) = valoarea de la 4 = *0x4 =>
0x5 12 Segmentation Fault
0x4 0
0x3 4 *b = 10; se modifică valoarea de la 0xE
0x2 7 *d = 10; Segmentation Fault
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 4
0xB 11 b = &a; adică b devine 0xF, adică 15
0xA 5
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 14
0xB 11 b = &a;
0xA 5 d = &c; adică d devine 0xE, adică 14
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 14
0xB 11 b = &a;
0xA 5 d = &c; adică d devine 0xE, adică 14
0x9 0
0x8 3
*b = 1; deci a devine 1
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 1
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 14
0xB 11 b = &a;
0xA 5 d = &c; adică d devine 0xE, adică 14
0x9 0
0x8 3
*b = 1; deci a devine 1
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 1
halfbyte a = 8, c = 5; Modificarea
0xE c = 10
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 14
0xB 11 b = &a;
0xA 5 d = &c; adică d devine 0xE, adică 14
0x9 0
0x8 3
*b = 1;
0x7 13
0x6 5
d[0] = 2; deci *(0xE +0) = 2
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 1
halfbyte a = 8, c = 5; Modificarea
0xE c = 2
halfbyte *b, *d;
0xD b = 15 variabilelor
0xC d = 14
0xB 11 b = &a;
0xA 5 d = &c; adică d devine 0xE, adică 14
0x9 0
0x8 3
*b = 1;
0x7 13
0x6 5
d[0] = 2; deci *(0xE +0) = 2
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a); afișează valoarea 8
0x8 3
0x7 13
0x6 5
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
print(a);
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
print(a); afișează valoarea 8
0x5 12 De ce? Ce s-a întâmplat la apel?
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 5
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 8
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE ainc = 8
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE ainc = 8
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0 - Execută instrucțiuni în funcție
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE ainc = 9
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0 - Execută instrucțiuni în funcție
0x3 4
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE ainc = 9
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0 - Execută instrucțiuni în funcție
0x3 4 - Golește stiva la terminarea apelului
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 9
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0 - Execută instrucțiuni în funcție
0x3 4 - Golește stiva la terminarea apelului
0x2 7
0x1 1
0x0 2
Exemplu didactic: procesor pe 4 biți
0xF a = 8
void inc(halfbyte a) { Apelul de
0xE 9
a++;
0xD 14
}
funcție
0xC 4
0xB 11
0xA 5 halfbyte a = 8;
0x9 0 print(a);
0x8 3
inc(a);
0x7 13
0x6 5
Un apel de funcție:
0x5 12 - Face o copie, pe stivă, a tuturor param
0x4 0 - Execută instrucțiuni în funcție
0x3 4 - Golește stiva la terminarea apelului
0x2 7
0x1 1
print(a); afișează valoarea 8
0x0 2
Alocarea dinamică a memoriei
Reminder Stivă (stack) vs Heap
Stivă Heap
• acces ff rapid • alocarea persistă și după
• se curăță automat la terminarea funcției
terminarea funcției • dimensiune nelimitată*
• spațiul gestionat eficient (nu • ceva mai lentă
se fragmentează) • trebuie să gestionăm noi
memoria (rezervăm/alocăm și
• doar pentru variabile locale eliberăm)
• dimensiune (mai mică decât • nu este gestionată eficient (se
heap-ul) dependentă de fragmentează)
sistemul de operare [1] • putem redimensiona
• dimensiunea variabilelor nu variabilele
poate fi modificată
*depinde totuși de memoria virtuală
Stivă (stack) vs Heap
Când folosim stiva? Când folosim heap-ul?
• date de dimensiuni mici • date de dimensiuni mari
• le folosim doar într-o • date care pot să-și schimbe
funcție dimensiunea în timp
• le știm de la început • date care trebuie să aibă
dimensiunea maximă (și durată de viață mare
aceasta nu se schimbă pe
parcursul programului)
null pointer
• Cum știm că un pointer este valid (îl putem
folosi)?
– un pointer este o adresă de memorie, dacă scriem
la o adresă pe care nu avem dreptul să o accesăm
=> segmentation fault
• Cum diferențiem un pointer inițializat de un
pointer neinițializat?
– amândoi pointerii punctează la o adresă care
poate fi validă
null pointer (NULL)
• avem nevoie de o adresă specială, care să nu fie validă
niciodată și care să o atribuim pointerilor ce nu pot fi
folosiți
• The language definition states that for each pointer type,
there is a special value--the ”null pointer”--which is
distinguishable from all other pointer values and which is
”guaranteed to compare unequal to a pointer to any
object or function.” That is, a null pointer points
definitively nowhere; it is not the address of any object or
function. The address-of operator & will never yield a null
pointer [3]
• in C null pointer-ul este reprezentat ca NULL și are valoarea
0
• în teorie pot exista și reprezentări diferite de 0 în memorie
pt NULL
null pointer (NULL)
• int *p;
• p=NULL; //p este inițializat cu NULL
• if(p) //sau if(p!=NULL) – verifică dacă p are o
adresă validă
• trebuie să avem grijă ca atunci când un
pointer nu mai are o adresă validă spre care să
puncteze să-i fie asignat NULL
• funcții care nu reușesc să returneze adrese
valide folosesc returnează tot NULL
Alocarea dinamică a memoriei
• alocarea dinamică a memoriei – rezervarea
unui spațiu de memorie a cărui dimensiune o
putem ști la compilare sau la rulare.
• pentru a putea utiliza spațiul rezervat adresa
de început a zonei de memorie este asignată
unui pointer
• în cazul în care alocarea nu reușește funcțiile
de alocare întorc NULL
malloc
• void* malloc (size_t size);
• alocă un număr de size octeti
• întoarce pointer la zona de date alocată sau
NULL în cazul în care alocarea nu reușește
• definită în stdlib.h
• size_t – unsigned long
Exemplu malloc
calloc
• void* calloc(size_t num, size_t size);
• num = numărul de elemente
• size = dimensiunea unui element
• toată zona de memorie alocată este inițializată cu
0
• ! ținând cont că NULL poate avea reprezentări pe
biți diferite de 0 dacă alocăm un vector de
pointeri nu este bine să ne bazăm pe inițializările
făcute de calloc
• take it with a grain of salt
Exemplu calloc
realloc
• void *realloc (void* ptr, size_t size);
• redimensionează zona de memorie spre care
punctează ptr la size octeți.
• dacă size este mai mare decât dimensiunea
inițială a blocului, zona suplimentară nu este
inițializată
• dacă realocarea nu reușește, întoarce NULL
realloc
• In cele mai multe situatii, puteti considera ca
ptr1=realloc(ptr2, ...);