PDA

Prikaži potpunu verziju : Dinamička alokacija memorije...


ozzytheking
10.1.2012, 18:06
Skoro sam krenuo da se interesujem za ovo posto C ne podrzava nizove sa promenljivom duzinom ali mi nesto nije jasno.
Ako sam dobro skapirao, malloc(size); rezervise size bajtova u memoriji i vraca pokazivac na taj rezervisani blok memorije. Ali kad ja rezervisem npr. size bajtova i nakon toga u taj niz unesem size + x (x > 0) necega (recimo karaktera, posto su oni po 1 bajt), kompajler se ne buni, program ne kresuje, sve je u redu iako sam ocigledno probio velicinu niza (koji je veliine size, a ja uneo vise od size clanova). Help! :o

Belphegor
10.1.2012, 18:22
...C ne podrzava nizove sa promenljivom duzinom.

realloc (http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/)

To ostaje na tebi da vodis racuna da ne pises/citas van granica niza! U ovom slucaju program moze, ali i ne mora da kresuje. Ovo obicno zovu "tempirana bomba".

ozzytheking
10.1.2012, 18:28
Aha. OK. Pod promenljivom duzinom sam mislio "unosenje velicine niza nakon sto se program pokrene" ali me mrzelo da pisem. :D
Jos nesto, onda bi za npr. niz short-ova pisao: malloc(sizeof(short)*koliko_shortova);?

Belphegor
10.1.2012, 18:33
Jos nesto, onda bi za npr. niz short-ova pisao: malloc(sizeof(short)*koliko_shortova);?

Da.

5char

Kosinus
10.1.2012, 20:49
Ili calloc( koliko_shortova, sizeof( short ) ); sto je potpuno isto.

EclipsE
10.1.2012, 22:43
calloc popuni alociranu memoriju nulama, dok malloc ne radi to.

Kosinus
10.1.2012, 23:07
Da, tim bolje jer ne mora da poziva memset ako mu zatreba da su lokacije napunjene nulama na pocetku.

voodoo_
10.1.2012, 23:12
Ipak ne treba koristiti calloc osim ako baš nije potrebno da imaš "čist" alociran prostor, čisto da se ne gubi na performansama.

ozzytheking
11.1.2012, 19:49
Nesto mi nije jasno, kada napisem malloc(sizeof(unsigned short)*blabla) i kasnije krenem da popunjavam taj prostor brojevima, program mi kresuje (sto je OK). I onda provalim da se problem resava tako sto napisem
malloc(sizeof(unsigned short *)*blabla). Ali, mi nije jasno zasto tako treba.
Provalio sam da je velicina (sizeof) pokazivaca uvek 4 bez obzira na sta on pokazuje sto je 99% uzrok kresovanja programa (jer je velicina short-a 2). Ali zar memorija alocirana sa malloc() ne treba da pamti promenljive tipa short, a ne (short *)?

voodoo_
11.1.2012, 20:31
Daj odlomak programa da ti kažemo gde grešiš

Inače veličina pokazivača je 4 bajta (32-bita) ako kompajliraš 32-bitni program. Ako praviš 64-bitni EXE, sizeof(pokazivač) biće 8 bajtova.

E sad, tvoj problem može biti to što si napravio niz dvobajtnih short-ova, a onda po njemu kreneš da pišeš u stilu

a[0] = 5

('a' je ono što si dobio s malloc-om)
s tim što će kompajler peticu tretirati kao običan 4-bajtni int, tako da probaj sa kastovanjem, npr

a[0] = (unsigned short) 5

A ovo malloc(sizeof(unsigned short *)*blabla) uopšte ne treba da radiš jer ti cilj svakako nije pravljenje niza pokazivača nego niza običnih celobrojnih vrednosti.

ozzytheking
11.1.2012, 21:07
Ni meni ne izgleda normalno da pravim niz pokazivaca, ali tako je jedino program radio normalno. Probao sam sa kastovanjem i isto se desava. Sve promenljive su tipa unsigned short.

unsigned short *queue, queue_start_pointer, queue_end_pointer;
//pretpostavljam da ovo moze (da ne moraju posebno pokazivaci a posebno promenljive)

void nekametoda()
{
...
free(queue);
queue = malloc(sizeof(unsigned short)*red_max*kol_max);
...
<while petlja koja puni/prazni queue uz pomoc enqueue() i dequeue() metoda>
//program kresuje kad se queue "napuni" na nekih 70%
//u vecini primera queue se ne napuni mnogo pa program radi normalno
}

void enqueue(unsigned short red, unsigned short kol)
{
queue[queue_end_pointer*2 + 0] = (unsigned short)red;
queue[queue_end_pointer*2 + 1] = (unsigned short)kol;
queue_end_pointer++;
}

void dequeue()
{
r = queue[queue_start_pointer*2 + 0];
k = queue[queue_start_pointer*2 + 1];
queue_start_pointer++;
}

voodoo_
11.1.2012, 21:44
Ako si zamislio da ti queue_start_pointer i queue_end_pointer takođe budu pokazivači, onda ti ne valja deklaracija, treba

unsigned short *queue, *queue_start_pointer, *queue_end_pointer;

A ako je ova dvojka u *2 veličina short-a, nemoj raditi takvo hardkodovanje nego uvek koristi sizeof.

Nešto sam sav šlogiran od umora pa ne mogu detaljno da analiziram program, samo mi je ovo prvo upalo u oči

ozzytheking
11.1.2012, 21:57
Zamislio sam ovako kako jeste (pokazivac, broj, broj) ali nisam bio siguran da valja. Mada, sad si odgovorio na to pitanje. :)
Dvojka nije velicina short-a nego broj kolona u "matrici" (posto ne znam kako da napravim matricu od dvostrukih pokazivaca - **, ili kako se vec zovu, napravio sam da se matrica cuva u nizu). Nulta kolona sluzi za cuvanje redova, a prva za kolone. To je u stvari matrica sa (red_max*kol_max) redova i 2 kolone. queue[queue_start_pointer*2 + 0] bi u stvari bilo queue[queue_start_pointer][0], a queue[queue_start_pointer*2 + 1], queue[queue_start_pointer][1]... :D

EclipsE
12.1.2012, 0:03
Dinamička matrica:

typedef unsigned short ushort; // lakse mi da pisem ushort

....
int i;
ushort **matrix = malloc(sizeof(ushort*) * VRSTA);

for (i = 0; i < VRSTA; i++)
matrix[i] = malloc(sizeof(ushort) * KOLONA);

....

// kada brises:
for (i = 0; i < VRSTA; i++)
free(matrix[i]);

free matrix;

Napraviš niz nizova :D

ozzytheking
12.1.2012, 1:55
OMG! Kako sam glup! :boodala: Provalio sam zasto ne radi. Niz queue treba da ima red_max*kol_max redova i 2 kolone, ali posto nisam znao kako da napravim matricu pomocu pokazivaca (hvala EclipsE, probacu), strpao sam sve u jedan niz ali njegova duzina je trebala da bude red_max*kol_max*2, a ne red_max*kol_max. :o

Geomaster
13.1.2012, 13:48
Ne moraš uopšte tako dinamički da alociraš matricu, ništa ne smeta da jednostavno napraviš jednodimenzionalan niz i koristiš ga kao matricu (u stvari, matrica u suštini i jeste jednodimenzionalan niz, pošto je memorija linearna :))

ozzytheking
19.1.2012, 18:59
Imam 2 pitanja.
1. Vidim da funkcija malloc() ne postavlja alocirani deo memorije na nula, vec su tu neki nasumicni brojevi, pa se setih i da neinicijalizovana promenljiva takodje ima neku nasumicnu vrednost. E sad, odakle ta nasumicna vrednost? Zar prazni deo memorije ne bi trebalo da bude uvek niz nula?

2. Zar velicina boolean promenljive nije 1 bit? Zasto sizeof(_Bool) vraca 1 (pretpostavljam da vraca broj bajtova, a ne bita)?
_Bool *p = malloc(5*sizeof(_Bool));
Sta se ovde desilo? :D malloc() alocira odredjeni broj bajtova. _Bool je 1 bit. Sta se desi kada hocu da (m)alociram niz bool promenljivih? Hoce li malloc da alocira (u ovom primeru) 5 bajtova i pritom da onih preostalih 7 bita po elementu niza (7*5 = 35) bleji neiskorisceno?

NISAM NESTO SMART
19.1.2012, 19:20
Nisam siguran za odg. ni na 1 ni 2 pitanje tako da ako sam se pr*sro izvinjavam se :D

1.Mozda zato sto kad se deo memorije oslobodi ta memorija se zapravo ne izbrise vec se samo naznaci da je slobodna i da moze da se prepise, pa kad alociras memorji ona ima vrednost prethodnog podatka koji je bio tamo.

2.Da velicina bool promenjive je 1 bajt a ne bit, to je i mene zanimalo, koliko sam razumeo ima veze sa nacinom s kojim kompjuter pristupa memoriji tako da najmanje mozes da rezervises jedan bajt. Tako da je zapravo bool promenjivoj samo 1 bit potreban ali mora biti velicine 1 bajta.

Belphegor
19.1.2012, 19:21
1. Memoriju mozes da zamislis ovako:

http://www.learncpp.com/images/CppTutorial/Section2/MemoryAddresses.png

i recimo na adresi 1 je bila neka promenljiva sa nekom vrednosti. Kad prestane da postoji, vrednost te promenljive ostaje zapisan na toj adresi, pa moze da se desi da taj program dodeli taj (sad slobodan) prostor preko malloc-a recimo.
Mislim, bar tako ja kapiram kako to izgleda.

edit:

#include <iostream>
#include <limits>

int main()
{
long adresa = 0;

{
int var = 345;
std::cout << "adresa promenjive var je " << &var << std::endl;
std::cout << "vrednost promenjive var je " << var << std::endl;
adresa = (long)&var;
}

std::cout << "-------------------------------------------------" << std::endl;

{
int* var2 = (int*)adresa;
std::cout << "adresa gde pokazivac var2 pokazuje je " << var2 << std::endl;
std::cout << "adresa pokazivaca var2 je " << &var2 << std::endl;
std::cout << "vrednost na adresi gde je nekad postojala var prom. je " << *var2 << std::endl;
}

std::cout << "Press enter to exit...";
std::cin.ignore( std::numeric_limits< std::streamsize >::max(), '\n' );
return 0;
}


2. Ne mozes da alociras manje od 1 bajta. Mada mozes sam da kreiras alokator bool-ova koji se tako ponasa.

edit: NISAM NESTO SMART super-ninja :D

NISAM NESTO SMART
14.3.2012, 23:35
Što se tice ovog skladistenja boolean vrednosti u jedan bit memorije, sad tek provalio da u C++ postoji bit fields(mozda je to opste poznato ali za mene je novost). Iako vidim da nije pametno koristiti zbog lose portabilnosti preko operativnih sistema valjda zbog big i little endian nacina sistema i razlike izmedju njih, ali vidim po netu da ima neke primene za low-level stuff i u networkingu.

Otprilike ovako mozes da se koristi za skladistenje vise bolean vrednosti u jedan bajt:

struct BitField
{
bool red : 1;
bool blue : 1;
bool white : 1;
//..itd
};

int main()
{
BitField color;
color.blue = 1;
if(color.blue)
//is't blue do something

return 0;
}

I ne moramo samo 1 bit da koristimo u slucaju bolean vrednosti samo 1 bit nam treba ali slobodno mozemo uzeti vise bitova.
Vise o ovome ovde (http://msdn.microsoft.com/en-us/library/ewwyfdbe(v=vs.71).aspx).