Newsgroup: it.comp.lang.c
Titolo: problema realloc

Salve a tutti,
ho un problema con la realloc.
In pratica se io metto una realloc in un ciclo for che rialloca la
stessa porzione di memoria più di 10 volte,aumentandola ogni volta di
un sizeof(int), dopo la decima riallocazione il prog si pianta e mi dà
errore. Ho sentito che questo è un bug del sistema di allocazione
della memoria di w98. E' vero..?...ho sbaglio io ?
Vi posto di seguito il sorgente in questione , che prende sa input da
tastiera tanti numeri quanti si vuole e li alloca in memoria
sufficiente a contenerli. Per terminare l'immissione dei numeri si
digita 0. Alla fine stampa tutti i numeri immessi.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
  int n,i=0;
  int *p=calloc(1,sizeof(int));
  int *np;
  if (!p) fprintf(stderr,"Errore di allocazione\n");
  fprintf(stdout,"Scrivi un numero: ");
  scanf("%d",&n);
  p[0]=n;
  while(1)
  {
    fprintf(stdout,"Inserisci un altro numero, 0 per terminare: ");
    scanf("%d",&n);
    if (n==0) break;
    if(!(np=realloc(p,++i))) fprintf(stderr,"Errore di
riallocazione\n");
    p=np;
    p[i]=n;
  }
  for(n=0;n<i+1;n++) fprintf(stdout," %d ",p[n]);
  free(p);
}
in questo codice ho provato anche a cambiare il puntatore ogni volta
che rialloco, ma il risultato è sempre uguale: dopo la decima
iterazione si pianta.
Grazie a chi mi aiuta.

     if(!(np=realloc(p,++i))) fprintf(stderr,"Errore di riallocazione\n");
qui invece.. gia' dal primo ciclo shrinki np ad un mero byte.. quando invece
te ne servirebbero 4 (
ALT! 4 su x86 32 bit blahblah niente digressioni sul fatto che io abbia
detto che un int è di 4 byte..
negherò spudoratamente! sappiamo tutti che non è vero. Ecco, diciamo che è
verosimile nel tuo caso,
windows98 su macchina a 32bit.)
cmq.. tanto che vuoi usare questo metodo.. tanto vale che la prima volta non
allochi affatto..
metti il puntatore a NULL e poi riallochi qui, dentro al ciclo, se leggi il
man di realloc infatti,
noterai che se passi NULL come pointer al blocco realloc funziona
esattamente come malloc..
sorvolo sul resto del codice in cui fai un andirivieni coi pointer in un
tripudio di non chiarezza
( hai le idee confuse? perche' usi un pointer d'appoggio che poi
riassegni? )
/*--------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
/*
    wrappare non ha mai fatto male a nessuno..
    oddio si.. pero' non c'e' morto.
*/
void* Realloc(void *block, size_t size)
{
    block=realloc(block,size);
    if (block==NULL)
    {
        fprintf (stderr,"Errore di riallocazione\r\n");
        exit(EXIT_FAILURE);
    }
    return block;
}
int main(int argc, char** argv)
{
    int in_numero,count,count2;
    int *pint /* birra! :P*/=NULL;
    for(count=0;;count++)
    {
        printf("Inserisci un %snumero, 0 per terminare:
",(count==0)?"":"altro ");
        scanf("%d",&in_numero);
        if (in_numero==0)
            break;
        pint=Realloc(pint,(count+1)*sizeof(int));
        pint[count]=in_numero;
    }
    for(count2=0;count2!=count;count2++)
        fprintf(stdout," %d ",pint[count2]);
    /* nello standard free(NULL) e' safe..
        tuttavia alcune vecchie (davvero vecchie)
        librerie hanno problemi :)
        dubito sia il tuo caso cmq :)
    */
    free(pint);
    /* una return mettiamola vah :) */
    return 0;
}
/*--------------------------------------------*/
la mia monetina nel secchio..
 Sbirish.

 predichi bene e razzoli male...
Al di la delle tue considerazioni (se i bug sono nel suo programma, non 
"dura" abbastanza per incappare nei bug di windows :P), c'era comunque un 
problema su alcune versioni di windows con la realloc: se non sbaglio la 
realloc falliva in alcuni casi (e comunque dopo qualche tentativo) in cui 
ci sarebbe stata ancora abbastanza memoria a disposizione, ovvero quando 
una realloc per N byte falliva, ma se tu provavi a fare una malloc su N 
byte questa ritornava con successo (tant'e' che si poteva ovviare al 
problema implementando una propria malloc).
Se non sbaglio se ne era parlato un po' di tempo fa' qui sopra (forse un 
post di Kronos?).
-- 
Mox
"Trust the programmer."
"Don't prevent the programmer from doing what needs to be done."
"Keep the language small and simple."
"Provide only one way to do an operation."

è gia' tanto che non crashi la prima volta =)
Grazie per la risposta :-)
comunque il fulcro del problema era la realloc, il resto delle
considerazioni su un programmino fatto in 47 secondi tanto per dare un
esempio lasciamole stare ;-)
Grazie milla.
p.s.: lasciamo stare anche le considerazioni per un post fatto in
0'22''34''' :))

[snipped]
6.3.6.1. Fixed in Service Pack 4:
 The following CRT issue has been fixed:
  Repeatedly using realloc on small memory blocks eventually caused a memory
access violation.
cmq qui si parla di C no? a prescindere dalle implementazioni.
Sbirish.

riassegni? )
il pointer d'appoggio era per tentare di risolvere il problema, dato
che ho letto su questo ng che usare un pointer d'appoggio poteva
aiutare, ma non č vero.
Comunque, anche facendo come tu dici, non ho risolto niente: si pianta
sempre dopo dieci riallocazioni.

> np=realloc(p,++i))
con la seguente.....
np=realloc(p,++i*sizeof(int))
e vedrai che forse funziona.
Concordo con gli altri, e con te, che il tuo programma sia fatto piuttosto
male. Ma capisco anche che e' solo uno studio sul realloc. Ad ogni modo ora
dovrebbe funzionare.
Tommy

np=realloc(p,++i*sizeof(int))
sì, avevo già provato a fare questo, e non si pianta più, ma alla fine
del programma mi da quest'errore:
runtime error R6017
- unexpected multithread lock error
da cosa dipende..?

 cmq qui si parla di C no? a prescindere dalle implementazioni.
Si, ma se l'implementazione non si comporta come previsto da standard, una 
nota per informare l'autore del post mi pare doverosa :)


 runtime error R6017
Dimmi se ti da ancora questo problema, se ora te lo da ancora, ora che il
codice e' piu' organizzato e piu' piacevole da leggerlo andro' nei dettagli
e leggero' e valutero' il significato di tutte le tue istruzioni che ho
copiato nel 99% dei casi cosi' come erano senza analizzarle.
In altre parole se ti da ancora il problema proveremo allora di
risolverlo.....
(se invece non te lo da piu', guarda che modifiche ho fatto e cerca di
capirne il motivo....)
Tommy

 da cosa dipende..?
heap corruption nel 99% dei casi.. reincolla e vediamo..
Sbirish.

 nota per informare l'autore del post mi pare doverosa :)
beh.. si parla tanto spesso di C99.. si presume che uno non abbia un
compilatore
anteguerra :)
--
sbirish

heap corruption nel 99% dei casi.. reincolla e vediamo..
no..il prog che ha fatto tommy non mi da' più nessun errore.
Credo di aver capito che il problema principale era la malloc iniziale
che io mettevo, dato che non sapevo la storia del puntatore null
inviato alla realloc ecc ecc, quindi credo di aver risolto il
problema. 
Sbirish, lo so che leggendo questi codici ti starai rivoltando sulla
sedia :-), ma il mio problema principale è capire, alla bellezza del
codice ci penso con più calma ;-).
Comunque grazie a tutti. Mi siete stati d'aiuto.
p.s.:
Qualcuno ha idea del perchè la malloc iniziale seguita dalle realloc
mi dava tutti quei problemi..?

 mi dava tutti quei problemi..?
Non credo fosse quello il problema. Io l'ho tolta in quanto era inutile.
Ti trovo un errore veloce veloce ma penso ce ne fossero altri....
int n,i=0;
int *p=calloc(1,sizeof(int));
p[0]=n;
[CUT]
if(!(np=realloc(p,++i*sizeof(int)))) fprintf(....
p=np;
p[i]=n;
Ok cerfchiamo di seguire cio' che accadeva:
p ha un intero allocato e giustamente nella pos 0 metti un valore.
poi riallochi sempre con 1, visto che i e' 0 ed ++i e' 1 !!!
A questo punto l'unica posizione disponibile e' sempre e solo p[0], ma tu
scrivi in p[i] che e' p[1] !!! ERRORE!
In pratica ogni volta (ciclo while) scrivi FUORI dalla memoria allocata!
Di questo dovresti essertene accorto visto che per stampare tutti i numeri
hai dovuto fare:
for(n=0;n<i+1;n++)
Non ti pare strano!?! (intendo quel +1)
In pratica penso che il problema fosse nell'implementazione
dell'"algoritmo", non nella malloc iniziale.
Ad ogni modo rimuovere la malloc iniziale toglie codice che altrimenti
sarebbe scritto 2 volte. (ma non e' essenziale).
Tommy
P.S. spero di esserti stato di aiuto.

 mi dava tutti quei problemi..?
se incolli il codice in questione.. molto volentieri .)
Uno Sbirish obfuscated C Contest :)

 mi dava tutti quei problemi..?
Non credo fosse quello il problema. Io l'ho tolta in quanto era inutile.
