2010-01-31 5 views
17

Il riferimento realloc dice:Come aggiornare altri puntatori quando realloc sposta il blocco di memoria?

La funzione può spostare il blocco di memoria in una nuova posizione, nel qual caso viene restituita la nuova posizione .

Vuol dire che se faccio questo:

void foo() { 

     void* ptr = malloc(1024); 

     unsigned char* cptr = (unsigned char*)ptr+256; 

     ptr = realloc(ptr, 4096); 
} 

poi CPTR possono diventare validi se realloc sposta il blocco?

Se sì, allora il segnale di realloc in qualche modo, che si sposterà il blocco, in modo che io possa fare qualcosa per evitare che CPPtr diventi non valido?

+0

Questa è una buona domanda +1 da parte mia poiché enfatizza la fondamentale curva di apprendimento che coinvolge realloc ... – t0mm13b

risposta

6

Sì, cptr non sarà più valido quando realloc sposta il blocco! E no, non vi è alcun accenno alla segnalazione di dire che sta spostando il blocco della memoria. A proposito, il tuo codice sembra incerto ... continua a leggere ... per favore vedi il mio answer ad un'altra domanda e leggi molto attentamente il codice su come usa realloc. Il consenso generale è che se si esegue questa operazione:

 
void *ptr = malloc(1024); 

/* later on in the code */ 

ptr = realloc(ptr, 4096); 

/* BAM! if realloc failed, your precious memory is stuffed! */ 

Il modo per aggirare questo è quello di utilizzare un puntatore temporanea e l'uso che, come mostrato:

 
void *ptr = malloc(1024); 

/* later on in the code */ 

void *tmp = realloc(ptr, 4096); 

if (tmp != null) ptr = tmp; 

Modifica: Grazie sicuro per indicare un gremlin che si è insinuato quando stavo scrivendo prima.

+0

Non è un codice reale, è solo qualcosa per mostrare quello che stavo per fare. Quindi c'è un modo per ridimensionare un blocco di memoria esistente senza spostarlo (o dire al programma che non è possibile?). Se chiamo realloc e succede spostando il blocco, allora è possibile mantenere in qualche modo validi i vecchi indirizzi, in modo da poter "annullare" il realloc? – zajcev

+0

No! Non puoi farlo ... questo dipende dal compilatore/linker/runtime. E no, non è possibile mantenere i vecchi indirizzi poiché l'heap si frammenterà nel corso e nella vita del programma. In breve, non si possono assolutamente annotare i vecchi indirizzi in quanto l'essenza stessa dei puntatori si basa sull'indirizzamento dinamico ... e non si può annullare il realloc ... – t0mm13b

+0

Questo è il cast più inutile del valore di ritorno di malloc I ' ho mai visto. E perché lanci il ritorno di malloc, ma non il ritorno di realloc? – Secure

3

Sì.

La cosa migliore da fare è confrontare ptr prima e dopo la riallocazione e verificare se è stata spostata. Non si dovrebbe assegnare un puntatore al valore di offset, ma si dovrebbe memorizzare l'offset e quindi indicizzare l'operatore originale con esso.

cioè

Invece di void* newPtr = ptr + 10; *newPtr = something;

Usa int new = 10; ptr[new] = something;

2

Sì, il CPTR diventa valida se realloc sposta il blocco.

+0

scusa per l'urlo ma ha aiutato a ottenere la risposta breve oltre il requisito di lunghezza minima. – bmargulies

4

Sì, cptr non sarà valido se realloc sposta il blocco.

No, non c'è segnale. Dovresti controllare il valore di ritorno rispetto alla posizione originale ptr.

4

Arriva un po 'tardi, ma la soluzione a questo problema (che nessuno ha menzionato) non è quella di utilizzare i puntatori nei blocchi assegnati che dovranno essere allocati. Invece, utilizzare gli offset a valori interi dal puntatore di base o (meglio) utilizzare un tipo struct e gli elementi membri per indirizzare posizioni specifiche nell'oggetto assegnato.

+0

Vorrei averlo passato prima che scrivessi il mio attuale incarico. Penso anche che questo sia parte della risposta al PO di zajcev, spiegando cosa può fare al riguardo. – gone