PDA

Visualizza la versione completa : [C] Errore nell'heap nella gestione di un array


toni00c
22-01-2011, 13:11
ciao ragazzi prendendo spunto da un libro ho creato un vettore dinamico di 10 elementi e ho pensato di gestirlo come in matematica si fa con le matrici (cioè con elementi che vanno da 1 a n )





#include <stdio.h>
#include <stdlib.h>




/* esercizio 2 */


int main ()

{
int *m ;
int n = 10 ;
int i ;

m = (int*) malloc (sizeof (int) * n ) ;
m-- ; /* non capisco questo pezzo */

for ( i = 1 ; i <= 10 ; i++ )
m[i] = 1 + rand () % 10 ;

for (i = 1 ; i <= 10 ; i++ )
fprintf(stdout ,"%d\n" , m[i] ) ;


free(m) ;

system ("PAUSE") ;

return 0 ;


}





dopo aver allocato lo spazio nella memoria con Malloc ho usato


m-- ;

per cambiare il primo elemento da 0 a 1 (prendendo spunto dal suddetto libro)




ora il programma mi genera un errore nell' HEAP ;

ho due domande da porvi :
1) in che modo "m-- " riesce a "slittare" gli elementi da "0-9" a "1-10" ,
e
2) da dove salta fuori quell'errore

grazie

_Alfabetagamma_
22-01-2011, 13:35
Diciamo che il libro ti risulta un po ostico. Se questa è la spiegazione di come funziona un array un po' di cose sono superflue:

1) è inutile fare una malloc (per dieci numeri andare a ottimizzare la gestione dello spazio mi sembra eccessivo). E se questa fosse la parte dinamica del tuo programma non ne vedo l'utilità :spy:
2) è inutile usare un fprintf, va benissimo il solo printf.

Allora siccome m diventa un puntatore (che puoi visualizzare come una casella dell'array), prima ti abbassa m di uno (se m puntava 22, ti fa puntare 21) poi fa partire il for con i che parte da 1. Questo comporta il fatto che m non parta da 21, ma da 22.

Quindi il tuo codice sarebbe molto più comodo così:



#include <stdio.h>
#include <stdlib.h>

int main ()

{
int m[10], i ;

for(i=0;i<10;i++)
/*metti quello che vuoi*/

for(i=0;i<10;i++)
printf("%i", i);

system ("PAUSE") ;

return 0 ;
}

toni00c
22-01-2011, 16:08
ciao quello che non riesco a capire ( al di la della comodità ) ( è solo un esercizio :p ) è come
il puntatore m si abbassi di 1

cioè :
scrivendo m-- , m non diventa -1 ?
cioè m è equivalente a &m[0] no?

YuYevon
22-01-2011, 16:44
Dopo l'allocazione dinamica, il puntatore m avrà un certo valore, diciamo 0x1234. Viene dunque decrementato di 1, il che significa che il suo valore viene decrementato di tanti byte quanti sono quelli che costituiscono il tipo di dato a cui il puntatore punta: se m è un puntatore a int e un int è su 4 byte, il valore di m una volta decrementato sarà 0x1230.
A quel punto nei due for successivi utilizzi gli indici a partire da 1 fino a 10 (anziché 0-9) perché scrivendo m[1] di fatto stai accedendo alla locazione di memoria successiva a quella dell'indirizzo base, ma visto che questo era stato decrementato di una posizione allora stai accedendo proprio alla prima componente dell'array allocato, utilizzando però l'indice 1 anziché 0 come sarebbe normalmente.
Prova a stampare un po' i valori degli indirizzi per renderti conto di tutto questo.
Quello che mi chiedo è come possa non darti un errore runtime l'istruzione free(m) visto che m, essendo stato decrementato, non è il valore originario dell'indirizzo al partire dal quale è stata allocata la memoria... dovresti sostituire quell'istruzione con free(m+1); o simili.

toni00c
22-01-2011, 17:04
Originariamente inviato da YuYevon
Dopo l'allocazione dinamica, il puntatore m avrà un certo valore, diciamo 0x1234. Viene dunque decrementato di 1, il che significa che il suo valore viene decrementato di tanti byte quanti sono quelli che costituiscono il tipo di dato a cui il puntatore punta: se m è un puntatore a int e un int è su 4 byte, il valore di m una volta decrementato sarà 0x1230.
A quel punto nei due for successivi utilizzi gli indici a partire da 1 fino a 10 (anziché 0-9) perché scrivendo m[1] di fatto stai accedendo alla locazione di memoria successiva a quella dell'indirizzo base, ma visto che questo era stato decrementato di una posizione allora stai accedendo proprio alla prima componente dell'array allocato, utilizzando però l'indice 1 anziché 0 come sarebbe normalmente.
Prova a stampare un po' i valori degli indirizzi per renderti conto di tutto questo.
Quello che mi chiedo è come possa non darti un errore runtime l'istruzione free(m) visto che m, essendo stato decrementato, non è il valore originario dell'indirizzo al partire dal quale è stata allocata la memoria... dovresti sostituire quell'istruzione con free(m+1); o simili.


perchè l'istruzione corretta è free (m+1)



ero convinto che con m-- decrementassi di 1 "componente" nel vettore , invece si tratta di byte ..
aritmetica dei puntatori..

scusa ma in questo modo

dire m-- ed m[0]-- è la stessa identica cosa no?
il puntatore m punta ad un area di memoria consecutiva di 10 "int" e il primo elemento è m[0] ;
ponendo m-- dovrebbe puntare a "qualcosa" prima dell elemento m [0] no?

grazie!

YuYevon
22-01-2011, 17:11
Originariamente inviato da toni00c
perchè l'istruzione corretta è free (m+1)


Ecco appunto, o anche free(++m);





scusa ma in questo modo

dire m-- ed m[0]-- è la stessa identica cosa no?


No, con m-- decrementi il valore del puntatore mentre con m[0]-- decrementi la prima componente dell'array (appunto quella di indice 0) che è cosa completamente diversa.



il puntatore m punta ad un area di memoria consecutiva di 10 "int" e il primo elemento è m[0] ;
ponendo m-- dovrebbe puntare a "qualcosa" prima dell elemento m [0] no?


Sì esatto, di fatto è come se puntasse a m[-1] con il valore originario di m. Dato però che tu utilizzi direttamente l'indice 1 nei due for, accedi al secondo elemento a partire dall'indirizzo m decrementato, che corrisponde quindi al primo del vettore.

_Alfabetagamma_
23-01-2011, 10:36
Allora siccome m diventa un puntatore (che puoi visualizzare come una casella dell'array), prima ti abbassa m di uno (se m puntava 22, ti fa puntare 21) poi fa partire il for con i che parte da 1. Questo comporta il fatto che m non parta da 21, ma da 22.


Ti avevo spiegato in maniera molto semplice cosa avveniva e poi suggerito un metodo diverso :)

toni00c
23-01-2011, 10:57
Originariamente inviato da _Alfabetagamma_
Ti avevo spiegato in maniera molto semplice cosa avveniva e poi suggerito un metodo diverso :)

ti ringrazio molto , sto facendo un po di fatica !
sbaglio o in questo forum ci sono diversi studenti?
lo sei anche tu?

_Alfabetagamma_
23-01-2011, 11:57
Si si, io sto studiando ing informatica, sono al primo anno, quindi non è che posso aiutare moltissimo, però se posso, mi fa piacere dare una mano :)

Loading