- 1 1. Sissejuhatus
- 2 2. malloc tähendab?
- 3 3. malloc põhiline kasutusviis
- 4 4. Miks on oluline vabastada mälu free() abil
- 5 5. Miks on oluline kontrollida NULL-i
- 6 6. Erinevus malloc ja calloc vahel
- 7 7. Praktiline näide: dünaamiline stringi mälu eraldamine malloc abil
- 8 8. malloc kasutamine struktuuride puhul
- 9 9. Levinumad vead malloc kasutamisel
- 10 10. Kokkuvõte
1. Sissejuhatus
Kui hakkad C-keeles programmeerima, puutud tõenäoliselt esmalt kokku massiivide ja sarnaste andmestruktuuridega, et hallata mälu. Kuid programmi keerukuse kasvades tekib vajadus paindlikuma mäluhalduse järele. Just sellistel hetkedel tuleb appi “dünaamiline mäluhaldus”. malloc
on üks selle keskseid funktsioone, mis võimaldab programmikäigu ajal dünaamiliselt vajalikku mälu reserveerida.
Võib võrrelda, et malloc
on nagu “toit, mis valmistatakse tellimuse alusel”, samas kui eelmääratud mälu (nagu massiiv) on “rootslaua stiilis toit”. malloc
abil “tellid” just nii palju mälu, kui vajad, ning kui oled lõpetanud, siis “tagastad taldriku” — ehk vabastad mälu free
funktsiooniga. Vaatame nüüd täpsemalt, kuidas malloc
töötab.

2. malloc
tähendab?
malloc
on lühend sõnadest “memory allocation” ehk “mälu eraldamine”, ning see on C-keeles kasutatav funktsioon dünaamilise mälu reserveerimiseks. Programmi käivitamise ajal saab selle abil reserveerida määratud suuruses mäluala, mille algusaadress tagastatakse. Nii saad kasutada ainult vajaminevat mälu hulka ning vältida fikseeritud suurusega massiivide piiranguid, saavutades paindlikuma mäluhalduse.
Praktilises koodis kasutatakse malloc
-i näiteks järgmiselt:
int *array = (int*)malloc(10 * sizeof(int));
Selles näites eraldatakse mälu kümne täisarvu jaoks. Oluline on mõista, et malloc
tagastab mäluala algusaadressi, kuid tüübituna ehk void*
. Seetõttu tuleb see sageli teisendada sobivasse tüüpi. Näites teisendatakse see (int*)
, et kasutada täisarvude massiivina.
3. malloc
põhiline kasutusviis
Vaatame nüüd malloc
-i kasutamist veidi üksikasjalikumalt. Selle lihtne süntaks on järgmine:
void* malloc(size_t size);
malloc
funktsioon võtab argumendina mäluala suuruse (baitides), mida soovid reserveerida. Kui eraldamine õnnestub, tagastatakse selle ala algusaadress. Tagastatud väärtus on tüüpi void*
, mis tähendab, et seda saab teisendada ükskõik millisesse andmetüüpi. Näiteks saab seda kasutada järgmiselt:
int *array = (int*)malloc(10 * sizeof(int));
Siin kasutatakse sizeof(int)
selleks, et määrata täpselt, kui palju mälu ühe täisarvu jaoks vaja on. See tagab, et programm töötab õigesti ka erinevates keskkondades. Kui oled mäluala kasutanud, on väga oluline see free
funktsiooniga vabastada. Kui seda ei tehta, võib tekkida probleem nimega mäluleke (memory leak).

4. Miks on oluline vabastada mälu free()
abil
Dünaamiline mäluhaldus on kindlasti mugav, kuid sellega kaasneb ka üks oluline kohustus: tuleb meeles pidada, et eraldatud mälu tuleb alati vabastada. Kui see unustada, tekib mäluleke — programm hakkab tarbetult palju mälu kasutama.
malloc
abil eraldatud mälu vabastatakse järgmiselt:
free(array);
Kui mälu ei vabastata, jääb see süsteemi ressursside hulka kuni programmi töö lõppemiseni. Pikaajaliste programmide puhul võib see põhjustada tõsiseid probleeme. Võib seda võrrelda olukorraga, kus sa võtad malloc
-iga köögist taldriku, aga ei too seda free
-iga tagasi — lõpuks saab köögis taldrikud lihtsalt otsa.

5. Miks on oluline kontrollida NULL
-i
malloc
funktsioon tagastab NULL
, kui mälu eraldamine ebaõnnestub. See võib juhtuda näiteks siis, kui soovitud mälumaht on liiga suur ja süsteem ei suuda seda eraldada. Seetõttu on malloc
-i kasutamisel oluline alati kontrollida, kas tagastatud väärtus ei ole NULL
. See on ohutu ja usaldusväärne programmeerimistava.
int *array = (int*)malloc(100000000 * sizeof(int));
if (array == NULL) {
// Käitumine juhul kui mälu ei õnnestu eraldada
printf("Mälu eraldamine ebaõnnestus.\n");
return 1;
}
Selline kontroll võimaldab teostada veatöötlust juhuks, kui mälu ei õnnestu eraldada. Pisike turvameede koodis aitab vältida suuri probleeme hiljem.

6. Erinevus malloc
ja calloc
vahel
Lisaks malloc
-ile pakub C-keel veel teise funktsiooni dünaamilise mälu eraldamiseks — see on calloc
. Kuigi malloc
ja calloc
on väga sarnased, on nende vahel mõned olulised erinevused. malloc
eraldab määratud suuruses mälu, kuid ei initsialiseeri seda. calloc
seevastu mitte ainult ei eralda mälu, vaid täidab kogu eraldatud ala nullidega.
calloc
kasutamine
int *array = (int*)calloc(10, sizeof(int));
See kood eraldab mälu 10 täisarvu jaoks ja initsialiseerib kõik elemendid nulliga. malloc
ja calloc
suurim erinevus seisneb selles, et calloc
võtab kaks argumenti: elementide arvu ja iga elemendi suuruse baitides. See muudab calloc
-i mugavaks massiivide ja muude mitmest elemendist koosnevate andmestruktuuride puhul.
Kumba kasutada, sõltub olukorrast: kui vajad nullidega initsialiseerimist, kasuta calloc
-i. Kui initsialiseerimine pole vajalik ja soovid paremat jõudlust, võib malloc
olla sobivam.
7. Praktiline näide: dünaamiline stringi mälu eraldamine malloc
abil
Siin vaatame praktilist näidet, kuidas kasutada malloc
-i stringi jaoks dünaamilise mälu eraldamiseks. Tavaliselt kasutatakse C-keeles stringide jaoks fikseeritud suurusega massiive. Kuid kui stringi pikkus selgub alles programmi töö ajal või kui soovid stringi dünaamiliselt töödelda, on malloc
väga kasulik.
char *str = (char*)malloc(50 * sizeof(char));
if (str == NULL) {
printf("Mälu eraldamine ebaõnnestus.\n");
return 1;
}
sprintf(str, "Hello, World!");
printf("%s\n", str);
free(str);
Selles näites eraldatakse mälu 50 märgi jaoks ning salvestatakse sinna tekst “Hello, World!”. Pärast kasutamist tuleb kindlasti vabastada eraldatud mälu free
funktsiooniga. malloc
võimaldab paindlikku mäluhaldust, mida fikseeritud suurusega massiivid ei paku.

8. malloc
kasutamine struktuuride puhul
Järgmisena vaatame näidet, kuidas kasutada malloc
-i struktuuri jaoks mälu dünaamiliseks eraldamiseks. Struktuurid on võimsad andmetüübid, mis võimaldavad koondada erinevat tüüpi andmeid. Ka nende mälu saab vajadusel dünaamiliselt hallata.
typedef struct {
int id;
char *name;
} Person;
Person *p = (Person*)malloc(sizeof(Person));
if (p == NULL) {
printf("Mälu eraldamine ebaõnnestus.\n");
return 1;
}
p->name = (char*)malloc(50 * sizeof(char));
sprintf(p->name, "John Doe");
p->id = 1;
printf("ID: %d, Nimi: %s\n", p->id, p->name);
free(p->name);
free(p);
Selles näites eraldatakse mälu Person
struktuuri jaoks ja seejärel veel eraldi name
välja jaoks. Nii saab iga struktuuri liiget vajadusel iseseisvalt hallata. malloc
abil saad paindlikult määrata, kui palju mälu igale väljal on vaja.
9. Levinumad vead malloc
kasutamisel
Räägime nüüd vigadest, mida algajad sageli malloc
kasutamisel teevad. Nende vigade vältimine aitab sul kirjutada turvalisemaid ja tõhusamaid programme.
- Mälu vabastamata jätmine
Kui unustadmalloc
-iga eraldatud mälufree()
abil vabastada, tekib mäluleke (memory leak). See on eriti probleemne pikaajaliste programmide puhul. Harjuta alati, et iga eraldatud mäluala vabastatakse. NULL
-kontrolli puudumine
Sageli unustatakse kontrollida, kasmalloc
tagastasNULL
. Kui mälu eraldamine ebaõnnestub ja seda ei kontrollita, võib programm käituda ettearvamatult. Lisa alatiNULL
-kontroll ja sobiv veatöötlus.- Initsialiseerimata mälu kasutamine
malloc
ei initsialiseeri eraldatud mälu. Kui proovid seda kohe kasutada, võivad tekkida vead. Kui vajad nullväärtusi, kaalucalloc
-i kasutamist.

10. Kokkuvõte
malloc
on võimas tööriist C-keeles, mis võimaldab dünaamilist mäluhaldust. Selle efektiivne kasutamine nõuab head arusaamist ja hoolikat mäluhaldust. Selles artiklis vaatasime läbi malloc
-i põhikasutuse, rakendamise stringide ja struktuuride puhul ning sellega seotud levinud vead. Kui kirjutad oma järgmist programmi, pea meeles: eralda mälu malloc
abil ja ära unusta seda hiljem free
funktsiooniga vabastada!
KKK
- Mida teha, kui
malloc
ei suuda mälu eraldada?
Kui mälu ei saa eraldada, tagastabmalloc
väärtuseNULL
. Kontrolli alatiNULL
-i ja rakenda sobiv veatöötlus. - Kumb on parem kasutada:
malloc
võicalloc
?
Kui initsialiseerimine pole vajalik, kasutamalloc
-i. Kui soovid, et eraldatud mälu oleks nullidega täidetud, siis kasutacalloc
-i.