PDA

View Full Version : Problema con array dinamici


Unrue
21-04-2006, 15:42
Mi capita una cosa strana. Nel mio programma dichiaro un array dinamico di interi:

int*nodiaperti;

All'interno di una funzione dichiaro : nodiaperti= new int[1000];

Alla fine della funzione dealloco il tutto : delete[] nodiaperti;

Quando richiamo la seconda volta la funzione, senza uscire dal programma, l'array viene ricreato ma non è vuoto. Alcune posizioni risultano occupate da numeri interi molto grossi. Ma perchè? Se dealloco l'array e lo rialloco, dovrebbe essere vuoto o sbaglio?

VICIUS
21-04-2006, 15:56
Non vorrei dire una cavolata ma la new non "pulisce" la zona di memoria allocata quindi ti restituisce un indirizzo di memoria valido che può essere pieno di robaccia. Sta a te ripulirla prima di cominciare ad usarla.

ciao ;)

Unrue
21-04-2006, 16:08
Non vorrei dire una cavolata ma la new non "pulisce" la zona di memoria allocata quindi ti restituisce un indirizzo di memoria valido che può essere pieno di robaccia. Sta a te ripulirla prima di cominciare ad usarla.

ciao ;)

Pensavo che questo compito lo facesse il delete[] . Pero' scusa, se devo azzerare tutto il vettore per riusarlo, perdo il vantaggio dell'allocazione dinamica.
Dichiarando int*nodiaperti = new int[1000] e magari uso solo 500 posti, gli altri 500 li risparmierei. Invece, se sono costretto ad azzzerare tutti e 1000 gli elementi, è come avere un array statico di 1000 elementi.

Angus
21-04-2006, 16:21
Pensavo che questo compito lo facesse il delete[] . Pero' scusa, se devo azzerare tutto il vettore per riusarlo, perdo il vantaggio dell'allocazione dinamica.
Dichiarando int*nodiaperti = new int[1000] e magari uso solo 500 posti, gli altri 500 li risparmierei. Invece, se sono costretto ad azzzerare tutti e 1000 gli elementi, è come avere un array statico di 1000 elementi.

Forse hai le idee un pò confuse. Per come la dichiari, nodiaperti è una variabile puntatore ad int. A questa variabile assegni l'indirizzo del primo elemento dell'array allocato staticamente (!) tramite l'operatore new. Quest'ultimo ha semplicemente trovato e riservato un'area consecutiva di memoria sufficientemente grande per contenere 1000 interi.

DISCLAIMER: non tocco C++ da troppo tempo ormai, ti conviene attendere qualche risposta più 'autorevole'.

VICIUS
21-04-2006, 16:42
Pensavo che questo compito lo facesse il delete[] .
Il compito della delete e dire al sistema operativo che il tuo programma non ha piu bisogno di quella memoria.

Pero' scusa, se devo azzerare tutto il vettore per riusarlo, perdo il vantaggio dell'allocazione dinamica.
Dichiarando int*nodiaperti = new int[1000] e magari uso solo 500 posti, gli altri 500 li risparmierei. Invece, se sono costretto ad azzzerare tutti e 1000 gli elementi, è come avere un array statico di 1000 elementi.
Il vantaggio della allocazione dinamica è che puoi allocare a tempo di esecuzione il numero esatto di elementi che ti servono. Se conosci a priori il numero di elementi che ti servono non ha senso usare l'allocazione dimanica. Se ti servono 372 elementi ne allochi 372, li azzeri per stare sicuro e poi li usi.

ciao ;)

71104
21-04-2006, 18:52
Mi capita una cosa strana. Nel mio programma dichiaro un array dinamico di interi:

int*nodiaperti;

All'interno di una funzione dichiaro : nodiaperti= new int[1000];

Alla fine della funzione dealloco il tutto : delete[] nodiaperti;

Quando richiamo la seconda volta la funzione, senza uscire dal programma, l'array viene ricreato ma non è vuoto. Alcune posizioni risultano occupate da numeri interi molto grossi. Ma perchè? Se dealloco l'array e lo rialloco, dovrebbe essere vuoto o sbaglio? vuol dire che usi Visual C++; ho indovinato? niente di grave comunque, vai di memset.

Unrue
21-04-2006, 20:44
Forse hai le idee un pò confuse. Per come la dichiari, nodiaperti è una variabile puntatore ad int. A questa variabile assegni l'indirizzo del primo elemento dell'array allocato staticamente (!) tramite l'operatore new. Quest'ultimo ha semplicemente trovato e riservato un'area consecutiva di memoria sufficientemente grande per contenere 1000 interi.

DISCLAIMER: non tocco C++ da troppo tempo ormai, ti conviene attendere qualche risposta più 'autorevole'.

Scusa se mi permetto ma l'operatore new non serve proprio per allocare dinamicamente qualcosa?. Se scrivo:

int*a= new int[10] a punta al primo indirizzo dell'array dinamico di interi.

Io non so a priori quanti elementi avrà questo array. Tale array cresce man mano che il programma avanza e ce li aggiunge. Io vorrei che al massimo mi occupasse 1000 posti,senza allocarli subito, quindi se alla fine ne ha utilizzati 500, gli altri 500 non li deve aver allocati. Non so se questo vuol dire memoria dinamica.

Unrue
21-04-2006, 20:49
vuol dire che usi Visual C++; ho indovinato? niente di grave comunque, vai di memset.

No, sto usando Borland C++ Builder 6

Unrue
21-04-2006, 20:50
Il compito della delete e dire al sistema operativo che il tuo programma non ha piu bisogno di quella memoria.


Il vantaggio della allocazione dinamica è che puoi allocare a tempo di esecuzione il numero esatto di elementi che ti servono. Se conosci a priori il numero di elementi che ti servono non ha senso usare l'allocazione dimanica. Se ti servono 372 elementi ne allochi 372, li azzeri per stare sicuro e poi li usi.

ciao ;)

Certo, questo lo so. Ma non so quanti elementi avro', per questo la uso :)

71104
22-04-2006, 01:39
No, sto usando Borland C++ Builder 6 aaargh :doh: :doh: :doh:
non avevo considerato la Borland :p :p :p

be' comunque la stessa cosa in determinati casi capita anche col VC++ :)

ciao

Unrue
22-04-2006, 11:57
aaargh :doh: :doh: :doh:
non avevo considerato la Borland :p :p :p

be' comunque la stessa cosa in determinati casi capita anche col VC++ :)

ciao

Mi sai dire se, quando scrivo int*a= new int[1000]
se alloco dinamicamente un'array di interi? Perchè sopra mi hanno detto che cosi' l'allocazione è statica. Ma allora a cosa serve l'operatore new quando do' una dimensione fissa all'array? New serve solo quando la dimensione non è specificata subito ma durante l'esecuzione?

Del tipo : int*a= new int[dim] e dim gli e la do' successivamente in fase di esecuzione, per esempio come input da tastiera.

shinya
22-04-2006, 12:35
Mi capita una cosa strana. Nel mio programma dichiaro un array dinamico di interi:

int*nodiaperti;

All'interno di una funzione dichiaro : nodiaperti= new int[1000];

Alla fine della funzione dealloco il tutto : delete[] nodiaperti;

Quando richiamo la seconda volta la funzione, senza uscire dal programma, l'array viene ricreato ma non è vuoto. Alcune posizioni risultano occupate da numeri interi molto grossi. Ma perchè? Se dealloco l'array e lo rialloco, dovrebbe essere vuoto o sbaglio?

La new allora uno spazio in memoria pari a quello che specifichi. Ma non puoi anche costringerla ad inizializzare tutta la memoria che alloca. Cosa vorresti ci fosse dentro? Tutti 0? Tutti 1? La new alloca la memoria, poi sta a te inizializzarla.
Se vuoi fare tutto in un colpo, in questo modo inizializzi tutto a zero:

nodiaperti = new int[1000]();


Altra cosa: e' buona norma poi mettere a zero il puntatore dopo la delete.


delete[] nodiaperti;
nodiaperti = 0;

Unrue
22-04-2006, 12:44
La new allora uno spazio in memoria pari a quello che specifichi. Ma non puoi anche costringerla ad inizializzare tutta la memoria che alloca. Cosa vorresti ci fosse dentro? Tutti 0? Tutti 1? La new alloca la memoria, poi sta a te inizializzarla.
Se vuoi fare tutto in un colpo, in questo modo inizializzi tutto a zero:

nodiaperti = new int[1000]();


Altra cosa: e' buona norma poi mettere a zero il puntatore dopo la delete.


delete[] nodiaperti;
nodiaperti = 0;



Quindi scrivere int*nodiaperti = new int[1000],

equivale a scrivere int a[1000];

int*nodiaperti= &a; ? Quindi è come fare l'allocazione statica se ho ben capito. Pero' io volevo che mi allocasse un elemento per volta , man mano che lo inserivo. Non tutti in un colpo. Per esempio, io credo che i vector facciano cosi, perchè si puo' dichiarare senza specificare le dimensioni, e poi inserire gli elementi con la pushback. In tal modo, alloca un elemento per volta, suppongo.

71104
22-04-2006, 12:48
Mi sai dire se, quando scrivo int*a= new int[1000]
se alloco dinamicamente un'array di interi? Perchè sopra mi hanno detto che cosi' l'allocazione è statica. Ma allora a cosa serve l'operatore new quando do' una dimensione fissa all'array? New serve solo quando la dimensione non è specificata subito ma durante l'esecuzione?

Del tipo : int*a= new int[dim] e dim gli e la do' successivamente in fase di esecuzione, per esempio come input da tastiera. così è dinamica:

int *a = new int[1000];
int *b = new int[dim];

e così è statica:

int a[1000];

inoltre alcuni compilatori (come il gcc) ti permettono anche di scrivere cose tipo

int b[dim];

ma sono veramente orribbili con due B.

shinya
22-04-2006, 13:01
Quindi scrivere int*nodiaperti = new int[1000],

equivale a scrivere int a[1000];

int*nodiaperti= &a; ? Quindi è come fare l'allocazione statica se ho ben capito.


Al massimo equivale a:

int a[10];
int *b = a; // dove 'a' equivale a &a[0]

E non è come l'allocazione statica, perchè puoi allocare memoria "su richiesta". E' chiaro che poi entrambe allocano memoria.

Pero' io volevo che mi allocasse un elemento per volta , man mano che lo inserivo. Non tutti in un colpo. Per esempio, io credo che i vector facciano cosi, perchè si puo' dichiarare senza specificare le dimensioni, e poi inserire gli elementi con la pushback. In tal modo, alloca un elemento per volta, suppongo.

Da quel che mi pare di capire, una lista sarebbe più pertinente come struttura.

Unrue
22-04-2006, 13:01
così è dinamica:

int *a = new int[1000];
int *b = new int[dim];



Pero' scusa, se scrivo :

int *a = new int[1000];

cosa c'e' di dinamico? La dimensione dell'array è fissata a priori.

Angus
22-04-2006, 14:59
Nessuno ha ancora precisato una cosa, di cui non sono più tanto sicuro:


int a[1000]; // alloca un array di 1000 interi nello stack
int* b = new int[1000]; // alloca un array di 1000 interi nello heap

Unrue
22-04-2006, 15:05
Nessuno ha ancora precisato una cosa, di cui non sono più tanto sicuro:


int a[1000]; // alloca un array di 1000 interi nello stack
int* b = new int[1000]; // alloca un array di 1000 interi nello heap


Si, questo è vero. pero' continuo a non capire cosa ci sia di dinamico se scrivo
int* b = new int[1000] . Io per dinamico intendo che l'allocazione la posso fare durante l'esecuzione. Se mi alloca subito 1000 interi non vedo cosa cambi dal punto di vista dell'occupazione di memoria, a parte che una scrive nello stack e l'altra nell'heap.

84seawolf
22-04-2006, 16:09
Prima di risponderti premetto che non ho ancora letto le altre risposte che ti hanno dato...quindi è probabile che hai già risolto il problema. Cmq...
Quello che accade è questo:

Con l'operatore delete non cancelli il contenuto della memoria; ciò che fa l'operatore delete è la seguente cosa:
restituisce al sistema la memoria precentemente occupata dalla variabile (la dealloca); ciò vuol dire che in qualche modo è come se si avvertisse il programma che lo spazio precedentemente occupato non serve + e quindi può essere nuovamente usato e sovrascritto.
Fai attenzione a quello che ho detto: SOVRASCRITTO!!!
questo significa che è possibile addirittura recuperare le informazioni contenute in una variabile (o array) precedentemente deallocate che non sono state ancora sovrascritte.
Probabilmente i "numeri interi molto grossi" che vedi sono informazioni contenute in quell'area di memoria che non servono +.

Prima di concludere vorrei dirti un'altra cosa:
per l'allocazione dinamica della memoria (e in particolare per creare array dinamici) esistono le STL (Standard template Library) che sono MOOOOLTO efficienti e facili da usare. come disse il mio prof. di programmazione: "è inutile inventarsi ogni volta la ruota".

Spero che questo messaggio ti è stato d'aiuto!

Unrue
22-04-2006, 21:24
Prima di concludere vorrei dirti un'altra cosa:
per l'allocazione dinamica della memoria (e in particolare per creare array dinamici) esistono le STL (Standard template Library) che sono MOOOOLTO efficienti e facili da usare. come disse il mio prof. di programmazione: "è inutile inventarsi ogni volta la ruota".

Spero che questo messaggio ti è stato d'aiuto!

Si lo so, infatti ho usato anche la classe template vector :)

Angus
23-04-2006, 13:31
Si, questo è vero. pero' continuo a non capire cosa ci sia di dinamico se scrivo
int* b = new int[1000] . Io per dinamico intendo che l'allocazione la posso fare durante l'esecuzione. Se mi alloca subito 1000 interi non vedo cosa cambi dal punto di vista dell'occupazione di memoria, a parte che una scrive nello stack e l'altra nell'heap.

Un array è un vettore nel senso più scolastico del termine: un insieme ordinato di n elementi. Il modo più semplice per rappresentarlo in informatica è proprio tramite un'area contigua di memoria che viene 'riservata'. L'allocazione di memoria è proprio l'atto di ricercare e di riservare un'area di memoria abbastanza grande per i propri scopi. La differenza tra dinamico e statico?


struct {
int age;
char name[64];
char surname[64];
} record;


Suppongo che di questa struttura non si possa cambiare l'allocazione di memoria di un membro a runtime.


struct {
int age;
char* name;
char* surname;
} record;


Di questa invece posso cambiare in qualsiasi momento l'allocazione di memoria di un suo membro.

DISCLAIMER: as above.

Unrue
23-04-2006, 16:27
Un array è un vettore nel senso più scolastico del termine: un insieme ordinato di n elementi. Il modo più semplice per rappresentarlo in informatica è proprio tramite un'area contigua di memoria che viene 'riservata'. L'allocazione di memoria è proprio l'atto di ricercare e di riservare un'area di memoria abbastanza grande per i propri scopi. La differenza tra dinamico e statico?


struct {
int age;
char name[64];
char surname[64];
} record;


Suppongo che di questa struttura non si possa cambiare l'allocazione di memoria di un membro a runtime.


struct {
int age;
char* name;
char* surname;
} record;


Di questa invece posso cambiare in qualsiasi momento l'allocazione di memoria di un suo membro.

DISCLAIMER: as above.


Quindi, se sscrivo : int+a = new in[1000] è un'allocazione STATICA.

int*a = new int[dim], con dim che gli e lo passo a runtime è DINAMICA, giusto?

Quindi le guide , un po' tutte sono un po' fuorvianti, perchè non specificano bene questa cosa. Dicono che l'operatore new, alloca dinamicamente memoria, in realtà l'alloca dinamicamente solo se il termine che specifica le dimensioni è una variabile passata a run time, non una costante.

84seawolf
23-04-2006, 17:04
Quindi, se sscrivo : int+a = new in[1000] è un'allocazione STATICA.

int*a = new int[dim], con dim che gli e lo passo a runtime è DINAMICA, giusto?

Quindi le guide , un po' tutte sono un po' fuorvianti, perchè non specificano bene questa cosa. Dicono che l'operatore new, alloca dinamicamente memoria, in realtà l'alloca dinamicamente solo se il termine che specifica le dimensioni è una variabile passata a run time, non una costante.

ASSOLUTAMENTE NO!! in entrambi gli esempi che hai fatto di utilizzo dell'operatore new si tratta di ALLOCAZIONE DINAMICA!!
L'allocazione dinamica si chiama così perchè mette le variabili in un'area di memoria particolare.
In dettaglio la RAM viene divisa in statica (detta stack) e dinamica (Heap).
La memoria statica si chiama così perchè è già "dimensionata" in fase di compilazione. Mentre quella dinamica solo a runtime!!
L'operatore new permette dunque di allocare memoria in fase di runtime e non in fase di compilazione

71104
23-04-2006, 17:47
[...]L'allocazione dinamica si chiama così perchè mette le variabili in un'area di memoria particolare.
In dettaglio la RAM viene divisa in statica (detta stack) e dinamica (Heap).[...] e il codice dove sta? :rolleyes:

e i dati inizializzati? e quelli non inizializzati? e le risorse? e le rilocazioni? e i simboli per il debug? e i TLS? e gli stack frames di thread diversi dal primario??? :rolleyes: :rolleyes: :rolleyes:

(per non parlare di tutto il resto)


@Unrue: l'istruzione

int *a = new[1000];

NON alloca staticamente memoria per 1000 interi; la alloca dinamicamente. le allocazioni statiche sono quelle che avvengono a compile-time, quelle dinamiche sono quelle che avvengono a runtime. new alloca sempre a runtime.

84seawolf
23-04-2006, 18:28
e il codice dove sta? :rolleyes:

e i dati inizializzati? e quelli non inizializzati? e le risorse? e le rilocazioni? e i simboli per il debug? e i TLS? e gli stack frames di thread diversi dal primario??? :rolleyes: :rolleyes: :rolleyes:

(per non parlare di tutto il resto)


@Unrue: l'istruzione

int *a = new[1000];

NON alloca staticamente memoria per 1000 interi; la alloca dinamicamente. le allocazioni statiche sono quelle che avvengono a compile-time, quelle dinamiche sono quelle che avvengono a runtime. new alloca sempre a runtime.

non ho capito bene se mi hai quotato per criticarmi oppure per confermare quello che ho detto.
Stavamo parlando delle variabili...cosa c'entrano le risorse e le SSL/TLS???
Cmq se proprio lo vuoi sapere una parte del codice viene caricato nella memoria statica....il rimanente (quando per esempio si utilizzano tecniche di polimorfismo) viene caricato man mano che serve nella parte dinamica in fase di runtime.

71104
23-04-2006, 18:42
non ho capito bene se mi hai quotato per criticarmi oppure per confermare quello che ho detto. ti ho quotato per portare avanti la guerra che combatto quotidianamente: è la mia sanguinosa battaglia contro il niubbismo informatico, e la combatto con tutto me stesso sia nella vita reale che in quella virtuale. INFORMAZIONE!!! :muro:

Stavamo parlando delle variabili...cosa c'entrano le risorse e le SSL/TLS??? ho parlato di dati inizializzati e non, di rilocazioni, di risorse, di simboli per il debug; era ovvio che mi riferivo al Thread Local Storage.

Cmq se proprio lo vuoi sapere una parte del codice viene caricato nella memoria statica.... "memoria statica" = "stack"? allora ti riferisci agli shellcode degli exploit di buffer overflow :p

il rimanente (quando per esempio si utilizzano tecniche di polimorfismo) viene caricato man mano che serve nella parte dinamica in fase di runtime. ti prego di farmi un esempio pratico in C o C++ di polimorfismo che causa allocazioni nell'heap: non vedo l'ora di verificare di persona col mio fido debugger.

84seawolf
23-04-2006, 19:27
ti prego di farmi un esempio pratico in C o C++ di polimorfismo che causa allocazioni nell'heap: non vedo l'ora di verificare di persona col mio fido debugger.

....esempio in C di polimorfismo è impossibile. (e questo lo dovresti sapere...altrimenti significa che non sai neanche cosa vuol dire programmare ad oggetti).
Per quanto riguarda l'esempio in C++ ti metto il link sull'articolo del polimorfismo di un'autorevolissimo sito (in inglese):
http://www.cplusplus.com/doc/tutorial/polymorphism.html

se pensi di saperne + di loro mandagli un'email e fammi sapere che ti rispondono.

Cmq per completezza ti metto una parte del codice:

// dynamic allocation and polymorphism
#include <iostream>
using namespace std;

class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
void printarea (void)
{ cout << this->area() << endl; }
};

class CRectangle: public CPolygon {
public:
int area (void)
{ return (width * height); }
};

class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
};

int main () {
CPolygon * ppoly1 = new CRectangle;
CPolygon * ppoly2 = new CTriangle;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ppoly1->printarea();
ppoly2->printarea();
delete ppoly1;
delete ppoly2;
return 0;
}


ah un'ultima cosa: quelli che tu chiami niubbisti vanno aiutati...e non "combattuti". Quelli come te dovrebbero avere un po + di umiltà...forse così hai la possibilità di crescere un po di + a livello intellettuale ( e non solo ).

Unrue
23-04-2006, 20:21
Signori per favore, facciamola finita, altrimenti la maggior parte delle risposte che trovo sono fra voi due contendenti, anzichè rispondere ai mei dubbi :) . Torniamo alla mia domanda. Io credo di aver capito le seguenti cose:

Se scrivo : int*a = new int[1000],

Il compilatore, alloca in fase di runtime un'array contiguo di 1000 interi. E lo mette nell'heap, perchè è un'allocazione dinamica.

Se scrivo int a[1000]; E' un'allocazione statica, quindi è effettuata prima del run time, e tale array, va nello stack. Quindi, dal punto di vista dell'occupazione di memoria, non cambia assolutamente nulla. Quello che cambia, sono le regole di visibilità dell'array, in quanto uno è nello stack, l'altro nell'heap.

QUindi, ritornando al mio progetto, l'allocazione dinamica non soddisfa ciò che volevo, ovvero inizializzare un'elemento per volta , man mano che lo creavo, perchè comunque l'operatore new mi alloca 1000 interi comunque. Devo allora usare o le liste o i vector, per allocare un'elemento per volta. Giusto?

Unrue
23-04-2006, 20:25
ASSOLUTAMENTE NO!! in entrambi gli esempi che hai fatto di utilizzo dell'operatore new si tratta di ALLOCAZIONE DINAMICA!!
L'allocazione dinamica si chiama così perchè mette le variabili in un'area di memoria particolare.
In dettaglio la RAM viene divisa in statica (detta stack) e dinamica (Heap).
La memoria statica si chiama così perchè è già "dimensionata" in fase di compilazione. Mentre quella dinamica solo a runtime!!
L'operatore new permette dunque di allocare memoria in fase di runtime e non in fase di compilazione

Probabilmente sono io che confondo il termine "dinamico". Pensavo che volesse dire che dà la possibilità di espandere un po' per volta un array. Invece vuol dire stabilire la dimensione dell'array durante l'esecuzione, ma una volta assegnata E' FISSA e non c'e' possibilità di "allungare " o "accorciare" il vettore, senza ridefinirlo ovviamente.

Angus
23-04-2006, 20:42
Signori per favore, facciamola finita, altrimenti la maggior parte delle risposte che trovo sono fra voi due contendenti, anzichè rispondere ai mei dubbi :) . Torniamo alla mia domanda. Io credo di aver capito le seguenti cose:

Se scrivo : int*a = new int[1000],

Il compilatore, alloca in fase di runtime un'array contiguo di 1000 interi. E lo mette nell'heap, perchè è un'allocazione dinamica.

Se scrivo int a[1000]; E' un'allocazione statica, quindi è effettuata prima del run time, e tale array, va nello stack. Quindi, dal punto di vista dell'occupazione di memoria, non cambia assolutamente nulla. Quello che cambia, sono le regole di visibilità dell'array, in quanto uno è nello stack, l'altro nell'heap.

QUindi, ritornando al mio progetto, l'allocazione dinamica non soddisfa ciò che volevo, ovvero inizializzare un'elemento per volta , man mano che lo creavo, perchè comunque l'operatore new mi alloca 1000 interi comunque. Devo allora usare o le liste o i vector, per allocare un'elemento per volta. Giusto?

Giusto, a parte qualche dettaglio. La cosa fondamentale da capire credo che fosse che i libri non mentono quando parlano di allocazione dinamica della memoria: semplicemente intendete due cose diverse.
Quello che confonde di solito è una struttura chiamata Vector associata ad una gestione della memoria apparentemente più simile a quella di una lista. In realtà non è detto, per motivi di complessità, che quelle strutture gestiscano la memoria come vorresti tu, cioè quel tanto che serve ogni volta.
Ma qui si entra nella teoria (e nella pratica) delle strutture dati e rischiamo di andare OT.

scusa Unrue, non avevo ancora visto il tuo ultimo post

Unrue
23-04-2006, 20:53
Giusto, a parte qualche dettaglio. La cosa fondamentale da capire credo che fosse che i libri non mentono quando parlano di allocazione dinamica della memoria: semplicemente intendete due cose diverse.
Quello che confonde di solito è una struttura chiamata Vector associata ad una gestione della memoria apparentemente più simile a quella di una lista. In realtà non è detto, per motivi di complessità, che quelle strutture gestiscano la memoria come vorresti tu, cioè quel tanto che serve ogni volta.
Ma qui si entra nella teoria (e nella pratica) delle strutture dati e rischiamo di andare OT.

scusa Unrue, non avevo ancora visto il tuo ultimo post

Di nulla figurati ;) . Il mistero è svelato, sono io che ho confuso il termine "dinamico" ( come puoi vedere nel mio post precedente) . Infatti, ho provato anche ad usare i vector. In un'altra discussione, mi sono accorto della lentezza del programma nell'usare i vector. Ma è normale ciò. Siccome il Vector alloca un elemento man mano che gli e lo passo( come volevo io !! :D ), non può allocare tutto consecutivamente come fa un array statico, perchè magari iniza a scrivere da una parte di memoria in cui c'e' posto solo per tre interi, al quarto, deve fare un salto in memoria, e ciò causa un rallentamento. Ancora peggio se copia tutto il vettore in un'area contigua(non so se fa il primo caso o il secondo). Grazie signori, i miei dubbi sono stati chiariti. se ho detto qualche cavolata adesso per favore, correggetemi :rolleyes:

shinya
23-04-2006, 20:53
ti ho quotato per portare avanti la guerra che combatto quotidianamente: è la mia sanguinosa battaglia contro il niubbismo informatico, e la combatto con tutto me stesso sia nella vita reale che in quella virtuale. INFORMAZIONE!!! :muro:

Non ho capito: la tua battaglia consiste nello sfottere chi ne sa meno di te o nell'indicare la strada a chi te la chiede?

84seawolf
23-04-2006, 21:06
Unrue ti ho appena trovato un articolo:

http://programmazione.html.it/guide/lezione/1185/i-puntatori/

e cmq sono d'accordo con shinya.

p.s. unrue scusa se mi sono attaccato con 7104...cercherò di non farlo +! :O

shinya
23-04-2006, 21:09
e cmq sono d'accordo con shinya.

p.s. unrue scusa se mi sono attaccato con 7104...cercherò di non farlo +! :O

Non c'è molto con cui essere d'accordo, non ho espresso un'opinione :) La mia era solo una domanda, non una provocazione.

84seawolf
23-04-2006, 21:13
infatti...sono d'accordo con il porgli quella domanda...

71104
23-04-2006, 21:14
....esempio in C di polimorfismo è impossibile. (e questo lo dovresti sapere...altrimenti significa che non sai neanche cosa vuol dire programmare ad oggetti). vedi? questa è la mia lotta. polimorfismo è un concetto più ampio di quello che probabilmente conosci tu. documentati su Wikipedia, io ho trovato questo (http://en.wikipedia.org/wiki/Polymorphism_(computer_science)) .
un esempio pratico: in C puoi assegnare un puntatore a char ad un puntatore a void senza bisogno di cast e senza che ne risulti un warning.

Per quanto riguarda l'esempio in C++ ti metto il link sull'articolo del polimorfismo di un'autorevolissimo sito (in inglese):
http://www.cplusplus.com/doc/tutorial/polymorphism.html

se pensi di saperne + di loro mandagli un'email e fammi sapere che ti rispondono. dove sta scritto in quella pagina che pezzi di codice se ne vanno allegramente nell'heap? e quali pezzi di codice per te se ne vanno nell'heap? ripeto che adesso che mi hai messo questa pulce nell'orecchio voglio verificare al più presto ;)

Cmq per completezza ti metto una parte del codice:

// dynamic allocation and polymorphism
#include <iostream>
using namespace std;

class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
void printarea (void)
{ cout << this->area() << endl; }
};

class CRectangle: public CPolygon {
public:
int area (void)
{ return (width * height); }
};

class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
};

int main () {
CPolygon * ppoly1 = new CRectangle;
CPolygon * ppoly2 = new CTriangle;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ppoly1->printarea();
ppoly2->printarea();
delete ppoly1;
delete ppoly2;
return 0;
}
e allora? ribadisco le domande precedenti.

ah un'ultima cosa: quelli che tu chiami niubbisti vanno aiutati... purché si mettano con l'approccio mentale di capire...

e non "combattuti". ma io combatto il niubbismo, non i niubbi.

taglio il resto dell'OT.

71104
23-04-2006, 21:29
Signori per favore, facciamola finita, altrimenti la maggior parte delle risposte che trovo sono fra voi due contendenti, anzichè rispondere ai mei dubbi :) . sorry, i forum sono fatti così ^^

Torniamo alla mia domanda. Io credo di aver capito le seguenti cose:

Se scrivo : int*a = new int[1000],

Il compilatore, alloca in fase di runtime il *programma*; comunque vabbè

un'array contiguo di 1000 interi. E lo mette nell'heap, perchè è un'allocazione dinamica. bravo; per essere ancora più esatti diciamo che le allocazioni dinamiche possono avvenire anche nello stack, ma sono molto rare (sono obbrobbri che fa solo il gcc -.-' ) quindi lasciamole perdere.

Se scrivo int a[1000]; E' un'allocazione statica, ovviamente

quindi è effettuata prima del run time, e tale array, va nello stack. AAAAAAARGH!!!! NOOOOO!!!! :muro:
poi si mettono a criticare me -_-'
tu sei una persona giustissimamente assetata di cultura, e impari ciò che ti si dice, e se ti si dicono inesattezze quelle impari; lascia perdere i consigli dei niubbi (e te lo dico in generale, non riferendomi specificamente al caso attuale).

allora: l'array che tu dichiari con int a[1000]; non va necessariamente nello stack: ci va solo se è dichiarato come variabile locale. invece se è dichiarato come variabile globale va in una sezione dati del tuo eseguibile finale, oppure se è membro di una classe va a finire nello stesso spazio dove è allocata la classe (che tipicamente è heap, ma può tranquillamente essere anche stack o sezione dati).

Quindi, dal punto di vista dell'occupazione di memoria, non cambia assolutamente nulla. no, infatti; sempre 1000 * sizeof(int) bytes sono.

Quello che cambia, sono le regole di visibilità dell'array, in quanto uno è nello stack, l'altro nell'heap. no; scordati l'associazione statico-stack, dinamico-heap.

QUindi, ritornando al mio progetto, l'allocazione dinamica non soddisfa ciò che volevo, ovvero inizializzare un'elemento per volta , man mano che lo creavo, perchè comunque l'operatore new mi alloca 1000 interi comunque. in realtà (sempre per motivi tecnici) non è detto: dipende da come è realizzato il runtime del compilatore che usi. con Borland C++ Builder comunque abbiamo visto che non va.

Devo allora usare o le liste o i vector, per allocare un'elemento per volta. Giusto? allocare un elemento per volta? se intendi riallocare dinamicamente l'array di volta in volta aggiungendo un elemento sappi che la cosa funziona ma è una pratica sconsigliata perché favorisce la frammentazione della memoria; non a caso spesso le classi che implementano array e vettori hanno nel costruttore un parametro di "preallocazione" per così dire, nel quale il programmatore specifica una sua previsione del numero di elementi che conterrà l'array: lo spazio viene preallocato dalla classe (anche se il numero iniziale di elementi ufficialmente risulta essere zero) in modo tale da evitare la frammentazione.

71104
23-04-2006, 21:36
Probabilmente sono io che confondo il termine "dinamico". Pensavo che volesse dire che dà la possibilità di espandere un po' per volta un array. si, anche; ma non specificamente. nel senso che ciò che tu dici è una immediata conseguenza della definizione di "allocazione dinamica" per come te l'ho data io (ovvero: allocazione che avviene in runtime).

Invece vuol dire stabilire la dimensione dell'array durante l'esecuzione, ma una volta assegnata E' FISSA e non c'e' possibilità di "allungare " o "accorciare" il vettore, senza ridefinirlo ovviamente. in C++ con new e delete no, ma in C si: devi usare realloc. però in C++ puoi sempre riallocare un nuovo array con new, ricopiare quello vecchio, aggiungere gli elementi nuovi, eliminare quello vecchio con delete, e assegnare al vecchio puntatore l'indirizzo del nuovo array. insomma, meglio usare STL :)

71104
23-04-2006, 21:39
Non ho capito: la tua battaglia consiste nello sfottere chi ne sa meno di te o nell'indicare la strada a chi te la chiede? la seconda di sicuro, altrimenti non starei su questo forum; per la prima... "sfottere" è soggettivo :Prrr:

84seawolf
23-04-2006, 22:20
scusa se insisto...non so tu che cosa intendi per heap...io (così come molti autori, manuali e tutorial) lo intendo come:

"Il termine Heap indica una porzione di memoria disponibile al programma, chiamata anche are di memoria dinamica. Lo heap e' l'area nella quale l'allocazione la deallocazione di memoria avviene in ordine sparso. Cio' vuol dire che se si allocano tre blocchi di memoria in sequenza, essi possono essere distrutti successivamente in qualsiasi ordine.
Lo heap e' una delle tre aree di memoria disponibili ad un'applicazione. Le altre due sono chiamate area di memoria globale (e' dove vengono create le variabili globali) e stack. Contrariamente allo heap, le variabili globali sono allocate quando il programma parte e rilasciate quando il programma termina."

oppure come: http://programmazione.html.it/guide/lezione/1185/i-puntatori/

potrei citarti anche molte altre definizioni simili prese da diversi libri di testo.

se tu hai una definizione diversa di memoria dinamica postala....così magari possiamo confrontarci (in modo costruttivo) e crescere tutti quanti ;)

71104
23-04-2006, 22:37
scusa se insisto...non so tu che cosa intendi per heap...io (così come molti autori, manuali e tutorial) lo intendo come:

"Il termine Heap indica una porzione di memoria disponibile al programma, chiamata anche are di memoria dinamica. Lo heap e' l'area nella quale l'allocazione la deallocazione di memoria avviene in ordine sparso. Cio' vuol dire che se si allocano tre blocchi di memoria in sequenza, essi possono essere distrutti successivamente in qualsiasi ordine. fin qui più o meno concordo, ma toglici il "chiamata anche area di memoria dinamica" (non l'ho mai sentito e mi pare veramente impreciso).

Lo heap e' una delle tre aree di memoria disponibili ad un'applicazione. mai sentita una cosa del genere :|
magari è solo una definzione molto imprecisa.

Le altre due sono chiamate area di memoria globale (e' dove vengono create le variabili globali) e stack. ancora ribadisco che un processo può avere N stack, tanti quanti sono i suoi thread (anzi ad essere pignoli ogni thread deve avere almeno due stack, ma è tutto un altro discorso che qui possiamo ignorare); e "area di memoria globale" non l'avevo mai sentita.

Contrariamente allo heap, le variabili globali sono allocate quando il programma parte e rilasciate quando il programma termina." ok.

se tu hai una definizione diversa di memoria dinamica postala.... non ce l'ho perché non l'ho mai sentita: "memoria dinamica" vuol dire tutto e niente, troppo generico, lo si può interpretare in duemila modi diversi a seconda del contesto.

parlando di gestione della memoria a livello tecnico come ne stiamo parlando ora io ho sentito solo "heap" (o "free store"), "stack", "sezioni dati" (o anche solo "dati")...

71104
23-04-2006, 22:47
oppure come: http://programmazione.html.it/guide/lezione/1185/i-puntatori/ l'ho letto: contiene imprecisioni/omissioni; sono poche, ma di fondamentale importanza (difatti chi le legge capisce facilmente cose errate).

ora io capisco perfettamente che certi argomenti siano di una complessità troppo elevata per essere spiegati in poche parole a dei principianti pur continuando allo stesso tempo a concentrare la spiegazione sul suo tema principale senza sfociare in un mare intricato di cose decisamente divaganti, ma allora è molto meglio non scriverle per nulla certe cose e rimandarle ad un corso più avanzato e più adatto.

Unrue
23-04-2006, 23:28
bravo; per essere ancora più esatti diciamo che le allocazioni dinamiche possono avvenire anche nello stack, ma sono molto rare (sono obbrobbri che fa solo il gcc -.-' ) quindi lasciamole perdere.



Vediamo se ho capito bene, ( se sbaglio non mi uccidere, sto imparando :) ) Un'allocazione dinamica va sicuramente nell'heap. Una statica, dipende dove viene fatta, giusto? Riguardo i vector invece. Se io dichiaro un vector di 100 interi, questi interi sono allocati in modo contiguo? La frammentazione quindi può accadere solo se inserisco un'elemento per volta. Quindi presumo che non conviene usare vector senza specificare la dimensione, in quanto si rishcia la frammentazione degli elementi in memoria.E riguardo la deallocazione, viene fatta in modo automatico presumo, ma l'area di memoria che era occupata, viene cancellata, o ci rimane porcherie dentro? Grazie :)

71104
24-04-2006, 00:03
Vediamo se ho capito bene, ( se sbaglio non mi uccidere, sto imparando :) ) Un'allocazione dinamica va sicuramente nell'heap. Una statica, dipende dove viene fatta, giusto? si

Riguardo i vector invece. Se io dichiaro un vector di 100 interi, questi interi sono allocati in modo contiguo? si, ovvio; che l'allocazione sia statica o dinamica mica può essere discontigua :p

La frammentazione quindi può accadere solo se inserisco un'elemento per volta. la frammentazione avviene con maggiore probabilità con frequenti riallocazioni di un qualche blocco di memoria; in realtà può anche accadere che riallochi un blocco 1000 volte aggiungendo ogni volta un kb e non frammenti nulla; ma può anche accadere che realloc (o un altro meccanismo di riallocazione) sia costretta a spostare il blocco perché incrementando la dimensione questo viene a collidere con altra memoria già allocata subito dopo; e se questa cosa accade per ogni elemento che aggiungi, dopo aver aggiunto 1000 elementi, be'... :)

Quindi presumo che non conviene usare vector senza specificare la dimensione, in quanto si rishcia la frammentazione degli elementi in memoria. be', tu semplicemente se usi quella classe e se sei in grado di fare una stima ragionevole se non addirittura lievemente abbondante di quanti elementi metterai nel vettore, sappi che sfruttare questo meccanismo di preallocazione non ti costa nulla e potrebbe anche giovarti un pochino in termini di performance; quindi perché non usarlo? :)
ma se non sei in grado di fare la stima (leggi: il vector può contenere un elemento come ne può contenere 10000) allora non ti scervellare e lascia che la memoria si frammenti, non muore nessuno :p
d'altronde le vere ottimizzazioni negli algoritmi dei programmi sono sempre quelle che riducono significativamente gli ordini asintotici di complessità degli algoritmi.

comunque se usi la classe vector delle STL allora guardati la differenza tra il metodo size() e il metodo capacity().

E riguardo la deallocazione, viene fatta in modo automatico presumo, ma l'area di memoria che era occupata, viene cancellata, o ci rimane porcherie dentro? Grazie :) non conosco STL così in dettaglio perché non la uso mai, ma presumo che il blocco venga deallocato automaticamente dal distruttore, anzi deve essere sicuramente così.

84seawolf
24-04-2006, 07:40
per una volta posso dire di essere d'accordo con 71104.

Volevo però aggiungere quanto segue (riguardo il modo in cui viene allocata la memoria dalla classe vector):

Se hai un vector di dimensione 4, e hai "riempito" tutte le 4 posizioni, quando ne inserisci una nuova, il vector alloca uno spazio in grado di contenere il DOPPIO della capacià che hai sfruttato fino a quel momento. Quindi se inserisci il quinto elemento, in realtà il vector ne ha allocati altri 4.

Questo potrebbe provocare un enorme sprego di memoria (pensa se hai un vector di dimensione 100000 e devi inserire l'100001-esimo elemento).
Tuttavia esiste il metodo resize per ridimensionare il vector....in pratica dealloca la memoria che non hai sfruttato.

Unrue
24-04-2006, 12:22
per una volta posso dire di essere d'accordo con 71104.

Volevo però aggiungere quanto segue (riguardo il modo in cui viene allocata la memoria dalla classe vector):

Se hai un vector di dimensione 4, e hai "riempito" tutte le 4 posizioni, quando ne inserisci una nuova, il vector alloca uno spazio in grado di contenere il DOPPIO della capacià che hai sfruttato fino a quel momento. Quindi se inserisci il quinto elemento, in realtà il vector ne ha allocati altri 4.

Questo potrebbe provocare un enorme sprego di memoria (pensa se hai un vector di dimensione 100000 e devi inserire l'100001-esimo elemento).
Tuttavia esiste il metodo resize per ridimensionare il vector....in pratica dealloca la memoria che non hai sfruttato.

Mi sembra una cosa poco intelligente allocare il doppio della capacità, poi magari mi sbaglio, ma non riesco a trovare il vantaggio.Mi puoi dire dove hai trovato questa informazione?

84seawolf
24-04-2006, 12:38
Beh...a dire il vero mi sembra un buon compromesso. Ti spiego subito il perchè:
se ad ogni nuovo inserimento il programma si dovesse preoccupare dell'allocazione di nuova memoria si avrebbe un notevole problema in termini di tempi di elaborazione.
Immagina che devi inserire 1000 elementi; Con questo metodo, il programma si deve preoccupare di allocare nuova memoria per sole 11 volte (anzichè 1000); infatti inserendo i vari elementi, la capacità del vector cresce nel seguente modo:
1
2
4
8
16
32
64
128
256
512
1024

E poi come già detto....se proprio non ti serve tutto lo spazio, esiste il metodo resize();

84seawolf
24-04-2006, 12:40
p.s. questa informazione l'ho avuta a lezione!! ;)

Cmq se trovo qualche articolo su internet ti faccio sapere...(prova a vedere manuali sulle stl)

84seawolf
24-04-2006, 13:02
ecco...trovato un'articolo in inglese. (cmq puoi consultare il prestigioso libro Deitel&deitl Tecniche avanzate di programmazione):

ti riporto parte dell'articolo:

If an element is added to a full vector, the vector increases its size—some STL implementations have the vector double its capacity.

preso da: http://www.deitel.com/articles/cplusplus_tutorials/20060120/Cplusplus_Tutorial2_VectorSequenceContainer/vectorSequenceContainers_Page3.html

Unrue
24-04-2006, 13:41
ecco...trovato un'articolo in inglese. (cmq puoi consultare il prestigioso libro Deitel&deitl Tecniche avanzate di programmazione):

ti riporto parte dell'articolo:

If an element is added to a full vector, the vector increases its size—some STL implementations have the vector double its capacity.

preso da: http://www.deitel.com/articles/cplusplus_tutorials/20060120/Cplusplus_Tutorial2_VectorSequenceContainer/vectorSequenceContainers_Page3.html

Mi sembra molto ben fatto. Grazie della dritta ;) e grazie a tutti quelli che mi hanno risposto, adesso ho capito tutto.