2010-10-31 9 views
23

Sto lavorando alla modifica di un programma C++ relativamente grande, dove purtroppo non è sempre chiaro se qualcuno prima di me usasse la sintassi C o C++ (questo è nel dipartimento di ingegneria elettrica di un'università, e noi EE siamo sempre tentati di usare C per tutto, e sfortunatamente in questo caso, le persone possono davvero farla franca).Oggetto C++ creato con nuovo, distrutto con free(); Quanto è grave questo?

Tuttavia, se qualcuno crea un oggetto:

Packet* thePacket = new Packet();

importa se si è distrutto con delete thePacket; o free(thePacket);?

Mi rendo conto che delete chiama il distruttore mentre free() no, ma Packet non ha un distruttore. Sto passando un periodo terribile in una palude di gestione della memoria e penso che questo possa essere uno dei tanti problemi.

+4

Il pacchetto ha un distruttore, anche se non è possibile vederlo. E '... gah, rispondi sotto. – slezica

+0

La risposta giusta è che non dovresti eliminare le cose. Avvolgili. – GManNickG

risposta

33

Sì, è importante.

Per la memoria ottenuti utilizzando new si must uso delete.

Per la memoria ottenuta utilizzando malloc è deve utilizzare free.

new e malloc possono utilizzare internamente diverse strutture di dati per tenere traccia di cosa e dove ha allocato la memoria. Quindi per liberare memoria, devi chiamare quella funzione corrispondente che sa di quelle strutture dati. Tuttavia, è generalmente una cattiva idea mescolare questi due tipi di allocazione di memoria in un pezzo di codice.

+4

'new' e' malloc' ** may ** utilizzano internamente strutture di dati differenti per tenere traccia delle allocazioni di memoria. Non devono. –

+1

Grazie! Solo il tipo di risposta che stavo cercando. Yaay per passare attraverso il codice di altre persone per vedere cosa hanno usato per creare cosa ... sarà divertente. Dmitri

+0

@Dmitri, ti sento :) e tu sei il benvenuto. Tempo per il potente grep – srean

19

Se si chiama free(), il distruttore non ottiene chiamato.

Inoltre, c'è no guarantee that new and free operate on the same heap.

È inoltre possibile ignorare new e delete per operare in particolare su una particolare classe. Se lo fai, ma chiama il numero free() invece del numero personalizzato delete, perdi qualsiasi comportamento speciale scritto in delete. (Ma probabilmente non chiedere a questa domanda se si fosse fatto che, a causa sapresti cosa comportamenti ti mancava ..)

+0

Grazie. Vedi il mio commento sul post di Omnifarious (stavo leggendo dal basso verso l'alto) – Dmitri

+0

@Dmitri, non stavo suggerendo di ridefinire 'delete' come soluzione - stavo sottolineando come un altro potenziale problema. Ho modificato la mia risposta per renderla un po 'più chiara. –

+0

Se si esegue l'override globale 'new' e' delete', allora * si deve * usare 'malloc()' e 'free()'. – wilhelmtell

4

Lei ha assolutamente ragione, è NON corretta. Come hai detto tu stesso, il libero non chiamerà il distruttore. Anche se Packet non ha un distruttore esplicito, sta utilizzando un ereditato.

L'utilizzo di free su un oggetto creato con new equivale a distruggere solo ciò che una copia superficiale raggiungerebbe. Distruggere profondamente HA BISOGNO della funzione distruttore.

Inoltre, io non sono sicuro che gli oggetti creati con new() sono sulla stessa mappa di memoria come malloc() 'd memoria. Non sono garantiti per essere, penso.

5

Packet ha un distruttore, anche se non è stato dichiarato in modo esplicito uno. Ha un distruttore predefinito. Il distruttore predefinito probabilmente non fa molto, ma non puoi contare sul fatto che sia così. Spetta al compilatore quello che fa.

new e malloc possono anche avere implementazioni molto diverse. Ad esempio, delete viene sempre chiamato in un contesto in cui ha informazioni perfette sulla dimensione della struttura dati che sta eliminando in fase di compilazione. free non ha questo lusso. È possibile che l'allocatore utilizzato da new non memorizzi i byte all'inizio dell'area di memoria indicando quanti byte occupa. Questo porterebbe free a fare completamente la cosa sbagliata e mandare in crash il programma quando si libera qualcosa assegnato con new.

Personalmente, se convincere la gente a fare la cosa giusta o il fissaggio del codice da soli è del tutto impossibile, vorrei dichiarare il mio globale operator new che ha chiamato malloc così allora free sarebbe sicuramente non in crash, anche se sarebbe ancora non chiamare il distruttore essere generalmente davvero brutti.

4

In breve, è grave quanto un comportamento non definito.

Questo è di per sé auto esplicativo.

C standard ($ 7.20.3.2/2) - "La funzione libera provoca lo spazio puntato ptr essere deallocato, cioè, rese disponibili per un'ulteriore assegnazione Se ptr è un puntatore nullo. , nessuna azione si verifica. In caso contrario, se l'argomento non corrisponde a un puntatore in precedenza restituito dalla calloc, malloc o la funzione realloc, o se lo spazio è stato deallocato da una chiamata a liberare o realloc, il comportamento è indefinito. "

1

se qualcuno crea un oggetto:

Packet* thePacket = new Packet(); 

importa se si è distrutto con thePacket eliminazione; o gratuito (thePacket); ?

Sì, è importante. free (thePacket) invocherà il comportamento non definito ma non lo sarebbe il delete thePacket e tutti sappiamo che il comportamento indefinito potrebbe avere conseguenze disastrose.

Problemi correlati