View Full Version : [C] realloc e funzione
salvodel
27-02-2008, 10:11
Salve a tutti,
ho un dubbio su come funziona realloc. Il problema è che se utilizzo il seguente programma preso da cplusplus
int main ()
{
int input,n;
int count=0;
int * numbers = NULL;
do {
printf ("Enter an integer value (0 to end): ");
scanf ("%d", &input);
count++;
numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers==NULL)
{ puts ("Error (re)allocating memory"); exit (1); }
numbers[count-1]=input;
} while (input!=0);
printf ("Numbers entered: ");
for (n=0;n<count;n++) printf ("%d ",numbers[n]);
free (numbers);
return 0;
}
come una funzione non mi gira.
In sostanza dichiaro
int * numbers = NULL;
nel main e poi lo passo alla funzione
int lettura(int *numeri)
All'interno della funzione riesco a vedere il contenuto dell'array che mi crea ma appena esco perdo il contenuto. Ovviamente nella mia funzione non c'è il free(numbers). Mi sembra che il realloc crei un'allocazione solo all'interno della funzione. Possibile che sia cosi o sto facendo un altro errore?
Grazie a tutti.
E' possibile che tu abbia lasciato una dicharazione locale, nella funzione, di
int * numbers = NULL;
Ovvero, non e' che per caso la tua funzione sta agendo su un array locale, senza gestire quello che e' il tuo array esterno?
Come ragionevolmente ti aspetti, le Malloc, realloc, etc. sono funzioni globali. La loro allocazione non viene persa al di fuori del contesto in cui sono state chiamate.
Attenzione ad usare realloc all'interno di una funzione eprché il puntatore ritornato da realloc può essere diverso da quello contenuto precedentemente in numbers.
Per tenere aggiornato numbers devi fare così:
void f(int **numbers)
{
.....
*numbers = (int*) realloc (*numbers, count * sizeof(int));
}
int *num = (int *) calloc(10, sizeof(int));
f(&num);
oppure:
int * f(int *numbers)
{
.....
numbers = (int*) realloc(numbers, count * sizeof(int));
.....
return numbers;
}
int *num = (int *) calloc(10, sizeof(int));
num = f(num);
commodoro
27-02-2008, 12:33
beh, credo che la seconda sia meglio in quanto a sintassi, cmq la dichiarazione di
int *numbers=NULL
debba essere fatta globalmente se si utilizza realloc in una funzione :D
@cionci: il tuo codice non considera l'eventualità che realloc ritorni NULL.
@cionci: il tuo codice non considera l'eventualità che realloc ritorni NULL.
Infatti è solo un esempio...noti i puntini ? Inoltre il punto cruciale era il passaggio alla funzione, non l'allocazione ;)
Infatti è solo un esempio...noti i puntini ? li noto, ma il primo esempio causa comunque un leak in quell'evenienza.
li noto, ma il primo esempio causa comunque un leak in quell'evenienza.
Non è detto...dipende da quello che metti nei puntini ;)
Ad esempio avrei potuto fare questo:
int *old = *numbers;
*numbers = (int*) realloc (*numbers, count * sizeof(int));
if(*numbers == NULL) free(old);
Che è anche più bello di fare:
int *newnumbers = (int*) realloc (*numbers, count * sizeof(int));
if(newnumbers == NULL)
{
free(numbers);
*numbers = NULL;
}
In ogni caso mi sembra superfluo preoccuparsi di un leak quando il 99% dei programmi deve abortire in caso che il valore di ritorno sia NULL, quella memoria verrà comunque liberata. Chiaramente se il programma non deve abortire si DEVE ad ogni costo preoccuparsi di questa evenienza, ma non è detto che si debba liberare la memoria.
salvodel
27-02-2008, 15:53
Attenzione ad usare realloc all'interno di una funzione eprché il puntatore ritornato da realloc può essere diverso da quello contenuto precedentemente in numbers.
Per tenere aggiornato numbers devi fare così:
Grazie a tutti per le risposte. Cionci scusa ma non ho capito cosa devo fare per tenere aggiornato il puntatore e cosa significa.
Per adesso ho risolto cosi: nel main alloco la memoria di numbers per un solo elemento(sono sicuro che uno lo deve avere per forza)
numbers=(int *)malloc(1*sizeof(int));
dopo di che utilizzo realloc solo nella function. In questo modo sembra funzionare.
Così è corretto oppure alcune volte potrebbe funzionare ed altre no?
Di nuovo grazie a tutti pewr i suggerimenti.
Te l'ho scritto sopra quello che devi fare, realloc può ritornare un puntatore diverso e quindi devi aggiornare il puntatore anche al chiamante...
salvodel
27-02-2008, 17:01
Te l'ho scritto sopra quello che devi fare, realloc può ritornare un puntatore diverso e quindi devi aggiornare il puntatore anche al chiamante...
Sinceramente non ho capito alcune cose tra cui perche fai una calloc di 10
int *num = (int *) calloc(10, sizeof(int));
Cmq adesso cerco di capire la spiegazione che ha dato questo bravo ragazzo nel 2002. Lo conosci?:D
http://www.hwupgrade.it/forum/showthread.php?t=271054
Sinceramente non ho capito alcune cose tra cui perche fai una calloc di 10
int *num = (int *) calloc(10, sizeof(int));
Era solo una prova ;) Va bene con qualsiasi dimensione avesse prima ;)
Cmq adesso cerco di capire la spiegazione che ha dato questo bravo ragazzo nel 2002. Lo conosci?:D
http://www.hwupgrade.it/forum/showthread.php?t=271054
Che tempi :asd:
salvodel
27-02-2008, 17:48
Era solo una prova ;) Va bene con qualsiasi dimensione avesse prima ;)
Che tempi :asd:
Queste sono le due funzioni riscritte con i tuoi consigli
int legge(struct mydata *data)
{
FILE *fdati;
double *tempread=NULL;
int *vetcanali;
int count, numcanali, punti;
int t, j, i;
sceltaING(&data, &vetcanali);
punti=(int) data->INFO[10];
numcanali=(int) data->INFO[0];
count=0;
tempread=(double *)malloc(1*sizeof(double));
if((fdati=fopen(stringa,"r"))==NULL)
printf("Impossibile aprire il file");
else
{
printf("Lettura dati in corso\n");
while(fscanf(fdati,"%le",&tempread[count])>0)
{
count++;
tempread = (double*) realloc (tempread, (count+1)*sizeof(double));
}
}
if((count/numcanali)>punti)
count=punti;
for(j=0;j<numcanali;j++)
{
printf("j=%d\n",j);
printf("canale=%d\n",vetcanali[j]);
}
for(t=0;t<count;t++)
for(j=0;j<numcanali;j++)
{
i=vetcanali[j]-1;
//printf("i=%d\n",i);
data->matrice[t][j]=tempread[i+t*numcanali];
}
fclose(fdati);
free(tempread);
printf("Lettura dati - O.K.\n");
return count;
}
/****************************************************/
int sceltaING(struct mydata *data, int **canali)
{
int ii,count,input;
count=0;
do {
printf ("Enter an integer value (0 to end): ");
scanf ("%d", &input);
if(input!=0)
{
count++;
printf("Ingresso diverso da 0.\n");
*canali = (int*) realloc (*canali, count * sizeof(int));
if (canali==NULL) {
puts ("Error (re)allocating memory");
exit (1);
}
canali[count-1]=input; /*Qui mi da un warning*/
printf("canali[%d]= %d\n",count-1,canali[count-1]);
}
} while (input!=0);
}
Il problema è che cosi mi si pianta dopo la prima assegnazione e mi da Segmentation fault (core dumped). Il warning dice assignment makes pointer from integer without a cast. Se riesci a buttargli una occhiata e a trovare l'errore sarebbe perfetto....non mi va di utilizzare quello mio che funziona ma che tu non hai trovato formalmente corretto.
Grazie e ciao
Chiaro, canali non la puoi utilizzare più così, ma devi utilizzarlo così:
(*canali)[i]
salvodel, non vorrei dirtelo, ma queste sono basi del C ;)
salvodel
27-02-2008, 18:08
Chiaro, canali non la puoi utilizzare più così, ma devi utilizzarlo così:
(*canali)[i]
salvodel, non vorrei dirtelo, ma queste sono basi del C ;)
Un po mi vergogno:( . Sto utilizzando il C con le basi di un solo esame. Il manuale che c'è in biblio è troppo "teorico" e non mi aiuta a risolvere questi casi. Ti ringrazio e chiedo scusa per il disturbo.
Non è detto...dipende da quello che metti nei puntini ;)
Ad esempio avrei potuto fare questo:
int *old = *numbers;
*numbers = (int*) realloc (*numbers, count * sizeof(int));
if(*numbers == NULL) free(old);
ENNO', perché i puntini nel primo esempio li hai messi solo prima della chiamata a realloc, non dopo :ciapet: :ciapet:
:D
ok basta :stordita:
cdimauro
29-02-2008, 08:48
Non è detto...dipende da quello che metti nei puntini ;)
Ad esempio avrei potuto fare questo:
int *old = *numbers;
*numbers = (int*) realloc (*numbers, count * sizeof(int));
if(*numbers == NULL) free(old);
Che è anche più bello di fare:
int *newnumbers = (int*) realloc (*numbers, count * sizeof(int));
if(newnumbers == NULL)
{
free(numbers);
*numbers = NULL;
}
In ogni caso mi sembra superfluo preoccuparsi di un leak quando il 99% dei programmi deve abortire in caso che il valore di ritorno sia NULL, quella memoria verrà comunque liberata. Chiaramente se il programma non deve abortire si DEVE ad ogni costo preoccuparsi di questa evenienza, ma non è detto che si debba liberare la memoria.
Non sempre: dipende dal s.o. e/o dal compilatore usato.
La deallocazione "automatica" delle risorse alla chiusura di un'applicazione è fortemente dipendente dalla piattaforma.
La deallocazione "automatica" delle risorse alla chiusura di un'applicazione è fortemente dipendente dalla piattaforma.
Ma parli di piattaforme embedded e sistemi realtime ?
cdimauro
29-02-2008, 13:18
Non solo: http://www.aros.org/
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.