2010-07-02 7 views
9

Ci sono garanzie che realloc() ridurrà sempre un buffer sul posto ?? In modo che il seguente:Realloc garantisce la presenza sul posto quando il buffer si sta restringendo?

new_ptr = (data_type *) realloc(old_ptr, new_size * sizeof(data_type)); 

darà sempre new_ptr == old_ptr se new_size < old_size (tranne ovviamente quando new_size == 0). Sembra ragionevole (per me) che funzionerebbe in questo modo, ma era curioso che lo standard lo imponesse.

Sto guardando la riallocazione di array di tipi di dati non-POD, e se il comportamento precedente è stato garantito pensava che la seguente strategia potrebbe almeno consentire efficiente "restringimento":

if (new_size > old_size) 
{ 
    // malloc() a new buffer 
    // use placement copy constructor to copy old objects over 
    // free() old buffer 
} 
else 
if (new_size < old_size) 
{ 
    // explicit destruction of unneeded objects 
    // realloc() buffer 
} 

I "mi aspetto che un" restringimento "sul posto sia solido anche se il tipo di dati avesse riferimenti/puntatori di auto o altro ...

+0

Grazie per i vostri commenti a tutti. Immagino che trovo abbastanza dispendioso e inefficiente dover allocare un nuovo buffer e fare una copia completa per ottenere un "restringimento" ... –

+0

Non aggiungendo al coro di "no" qui, dovresti ottenere il idea ormai. Ma un involontario effetto collaterale di garantire che il blocco riallocato riutilizzi la stessa memoria quando ridotto è che non si poteva usare un [piccolo allocatore di oggetti] (http://www.developer.com/ws/brew/article.php/3315011 /Small-Memory-Allocation.htm) all'interno di malloc/realloc, poiché questi allocatori raggruppano insieme oggetti di uguale dimensione. –

+0

Un altro motivo per cui non è possibile aspettarsi che realloc riutilizzi sempre la stessa memoria è che la maggior parte degli heap generici mette le informazioni di gestione (dimensione del blocco, puntatore al prossimo blocco nell'heap) in un'intestazione a destra "in primo piano" della memoria allocata. Quindi, se si dispone di un blocco che si trova tra due blocchi allocati e riallocato in una parola più piccola, non ci sarebbe spazio per inserire l'intestazione per la parola libera della memoria, perdendola effettivamente e frammentando in modo permanente il proprio heap. –

risposta

7

No.

Questo è tutto. Niente di tutto ciò "potrebbe funzionare in alcune architetture" o "dovrebbe basarsi sull'esperienza". Lo standard afferma chiaramente che l'indirizzo può cambiare in modo da fare affidamento su che e nient'altro.

In termini di codifica standard: fare o non. Non c'è un "provare" :-)


Da C99:

La funzione realloc dealloca il vecchio oggetto puntato da ptr e restituisce un puntatore a un nuovo oggetto che ha la dimensione specificata da dimensione. Il contenuto del nuovo oggetto deve essere uguale a quello del vecchio oggetto prima della deallocazione, fino al minore tra le nuove e le vecchie dimensioni. Qualsiasi byte nel nuovo oggetto oltre la dimensione del vecchio oggetto ha valori indeterminati.

Se ptr è un puntatore nullo, la funzione realloc si comporta come la funzione malloc per la dimensione specificata.Altrimenti, se ptr non corrisponde a un puntatore precedentemente restituito dalla funzione calloc, malloc o realloc, o se lo spazio è stato deallocato da una chiamata alla funzione libera o realloc, il comportamento non è definito. Se non è possibile allocare la memoria per il nuovo oggetto, il vecchio oggetto non viene deallocato e il suo valore è invariato.

La funzione realloc restituisce un puntatore al nuovo oggetto (che può hanno lo stesso valore come un puntatore alla vecchia oggetto), o un puntatore nullo se il nuovo oggetto non può essere allocato.

0

No, non esiste tale garanzia.Le implementazioni di realloc possono semplicemente ridurre il buffer in luogo, ma non sono costretti a farlo.

2

Generalmente lo fa, ma non è garantito (dipende tutto dalla tua architettura). Quindi Non si dovrebbe fare affidamento su di esso su tale comportamento

EDIT:

di riferimento: http://opengroup.org/onlinepubs/007908775/xsh/realloc.html

In caso di superamento di una dimensione diverso da 0, realloc() restituisce un puntatore allo spazio assegnato (eventualmente spostato) .

1

Alcuni allocatori utilizzano una strategia di "bucketizzazione" in cui le allocazioni vengono ridimensionate, ad esempio da 2^3 a 2^4, allo stesso bucket di allocazione. Ciò tende a prevenire casi estremi di frammentazione della memoria in cui molte piccole allocazioni diffuse nell'heap impediscono il successo di allocazioni di grandi dimensioni. Ovviamente, in tale gestore di heap, la riduzione della dimensione di un'allocazione potrebbe forzarla in un bucket diverso.

5

No. Non si deve fare affidamento su questo.

Secondo spec 7.20.3.4/4:

La funzione realloc restituisce un puntatore al nuovo oggetto (che può hanno lo stesso valore come un puntatore alla vecchia oggetto ), o un puntatore nullo se il nuovo oggetto non può essere assegnato a .

+3

+1 per il testamento. :-D –

+0

+1 Owen per l'approfondimento (: – Poni

Problemi correlati