2009-09-09 10 views
28

Perché si dovrebbe utilizzare la funzione realloc() per ridimensionare un array assegnato dinamicamente anziché utilizzare la funzione free() prima di richiamare nuovamente la funzione malloc() (vale a dire vantaggi e svantaggi, vantaggi vs. svantaggi, ecc.)? È per la programmazione in C, ma non riesco a trovare il tag corretto per questo. Grazie in anticipo.Differenze tra l'utilizzo di realloc vs free -> funzioni malloc

+0

Perché hai bisogno di memoria se non ti interessa il suo contenuto? – Philip

risposta

20

Il vantaggio è che realloc conserverà il contenuto della memoria. Con free + malloc avresti bisogno di resettare i dati nella matrice.

+4

che è anche lo svantaggio. Se non sei interessato alla conservazione dei dati, in alcuni casi il libero e malloc potrebbero essere più veloci (dove il blocco di memoria deve essere spostato a causa della crescita delle dimensioni) – Toad

+7

È più veloce da riallocare e potrebbe essere più veloce da riallocare se c'è spazio per crescere sul posto. Altrimenti, si traduce in un malloc/copy/free. –

+1

ancora ... se non hai bisogno di conservare i dati, un malloc gratuito e sembra più descrittivo di quello che stai facendo. – Toad

6

Bene, realloc può modificare la dimensione del blocco in posizione o assegnarne una nuova e copiare quanto si adatta. Al contrario, malloc e free insieme possono solo assegnarne uno nuovo e devi fare la tua copia.

Per essere sinceri, realloc non ha molto senso in questi giorni perché non funziona bene con C++. Di conseguenza, c'è stata una tendenza per i gestori di memoria a non ottimizzare per questo.

+1

La tua affermazione riguardo i gestori di memoria e realloc non l'ottimizzazione per esso - hai letto qualcosa in merito a questo? – ArmenB

+0

@ArmenB. Non sono sicuro di cosa stavo pensando nel 2009, ma da allora ho guardato il codice per TCMalloc e non è davvero orientato al ridimensionamento. –

1

"piuttosto che usare la funzione free() prima di chiamare la funzione di nuovo malloc()"

Se si libera la matrice esistente, hai perso tutto il suo contenuto, così non si può "crescere" la matrice in il solito senso.

+0

Sono sicuro che volevano dire che avrebbero chiamato malloc, copiare le cose e poi liberarle. –

+0

Steven ha appena detto cosa intendevo. – stanigator

3

Avevo un programma che stava facendo un sacco di chiamate gratuite() e malloc() per creare un array dinamico, e ho pensato che avrei ottimizzato riutilizzando l'array esistente quando possibile. I benchmark hanno mostrato che realloc() in media è più lento del semplice chiamare free() e malloc(). Immagino che abbia senso, dato che a volte potrebbe crescere e forse richiedere una copia.

11

So che questa domanda è molto vecchia (è stata risposta nel 2009) ma spero che la mia risposta aiuti chi cerca e trova questa domanda (come me).

Anche se questo riferimento non è definitiva in quanto la gestione della memoria varia a seconda dei diversi sistemi, al giorno d'oggi le cose tendono ad essere abbastanza standardizzata, per cui questi risultati dovrebbero essere sicuri da usare come punto di riferimento (Se siete a conoscenza di un caso reale di vita IT non è, per favore dimmi). Utilizzo Windows 7 su un processore Intel Core i3 2310M Quad Core da 2,10 GHz con 4 GB di RAM. Non il miglior hardware di sempre, ma il migliore che ho adesso.

Ciò che fa questo benchmark è che inizia con una certa quantità di memoria (INITIAL_MEMORY) e si rialloca ripetutamente per piccole quantità (BYTE_STEP) finché non alloca completamente/deallocola ALLOCATE_MEMORY. Per questo, prova 6 approcci:

  1. Aumento di Malloc perdita: free() e malloc() più memoria.
  2. Diminuzione malloc di Lossful: gratuito() e malloc() in meno memoria.
  3. Aumentando Malloc: malloc() più memoria, copia dati e memoria precedente() precedente.
  4. Diminuendo Malloc: malloc() meno memoria, copia dati e memoria precedente() precedente.
  5. Aumentare Realloc: realloc() più memoria.
  6. Riduzione di Realloc: realloc() meno memoria.

Quindi, prima prova: Inizia con 2MB e allocare ± 1 MB in passi da 1 KB:

Increasing Lossful Malloc took 3 ms 
Decreasing Lossful Malloc took 5 ms 
Increasing Malloc took 1 265 ms 
Decreasing Malloc took 744 ms 
Increasing Realloc took 316 ms 
Decreasing Realloc took 0 ms 

Come possiamo vedere, copiando manualmente con memcpy è sempre più lento di realloc, perché in questo scenario malloc è garantito per allocare nuova memoria e sei costretto a copiare i dati in ogni allocazione, il che ci mostra che realloc sta effettivamente riutilizzando lo stesso indirizzo e ingrandendo le dimensioni del blocco in alcuni casi. Quindi se vuoi conservare i tuoi dati, realloc è probabilmente quello che vuoi usare. Per semplificare le cose, non continuerò a testare questo approccio malloc lossless.

Procediamo alla prova successiva: 32 MB di memoria iniziale, l'assegnazione di 16 MB in incrementi 16KB:

Increasing Lossful Malloc took 4 ms 
Decreasing Lossful Malloc took 4 ms 
Increasing Realloc took 21 453 ms 
Decreasing Realloc took 0 ms 

Ora, possiamo vedere che l'aumento realloc prende un sacco di tempo rispetto agli altri test. La riduzione di realloc non ha nemmeno raggiunto 1 ms. Questo dimostra che se non vuoi conservare la memoria dovresti usare un approccio free-> malloc o no? Guardano questi risultati:

Increasing Lossful Malloc took 777 ms 
Decreasing Lossful Malloc took 729 ms 
Decreasing Realloc took 19 ms 

(. Questi risultati erano troppo vicini, quindi eseguire numerosi test e media)

Sicuramente diminuendo la dimensione della memoria è più efficace quando utilizza realloc(). Questo probabilmente perché realloc non ha bisogno di cercare un nuovo blocco di memoria, usa solo il precedente e lo riduce. Questa è una grande differenza di prestazioni se si utilizza pesantemente l'allocazione.

Inoltre, possiamo vedere che l'aumento di malloc è leggermente più lento di quello decrescente, anche quando entrambi fanno praticamente lo stesso: trovare un blocco di memoria e allocarlo. Questa differenza è probabilmente dovuta al fatto che durante la ricerca di blocchi più grandi, malloc ha bisogno di cercare più a lungo in media rispetto alla ricerca di blocchi più piccoli. Ad esempio, se esiste un blocco di 30 MB, un malloc che assegna 16 MB lo userebbe, ma un malloc che assegna 32 MB dovrebbe saltarlo e continuare a cercare e utilizzare il tempo di attività. Questo è probabilmente il motivo per cui i risultati sono stati così diversi nei miei test.

In conclusione/TLDR:

  1. Se è necessario per mantenere i vostri dati, utilizzare realloc(). È ~ 4 volte più veloce rispetto all'utilizzo di malloc()/free() e copia i tuoi dati quando aumenta di livello. Quando si ridimensiona lo in basso, lo è 10.000-100.000 volte più veloce. MAI copiare le cose manualmente.
  2. Se non bisogno di conservare i dati, è necessario utilizzare malloc()/free() per scala fino (aumentare la dimensione della memoria), ma usare realloc() quando ridimensionamento (riducendo la dimensione della memoria).
  3. Se non si conosce la dimensione precedente (non si sa se si sta ridimensionando o aumentando), utilizzare malloc()/free(). Quando si ridimensiona, realloc() è ~ 40 volte più veloce, ma quando si scala, realloc() è ~ 7600 volte più lento. A meno che il tuo programma non faccia grandi allocazioni e tonnellate di piccole deallocazioni (circa 200 volte più deallocations che allocazioni, che è possibile ), dovresti usare malloc()/free().

Ecco la mia fonte di riferimento: test.cpp

Ora, per favore, se ho fatto qualcosa di sbagliato o avete qualsiasi commento, sentitevi liberi di dire/correggermi.

Problemi correlati