Tutti ti hanno già detto che non dovresti fare questo e che causerà un comportamento indefinito. Questo è ampiamente noto, quindi approfondiamolo su un livello più basso e vediamo cosa succede realmente.
La risposta universale standard è che tutto può accadere, che non è completamente vero. Ad esempio, il computer non tenterà di ucciderti per farlo (a meno che tu non stia programmando l'intelligenza artificiale per un robot) :)
Il motivo per cui non può esserci alcuna risposta universale è che, poiché questo non è definito, potrebbe differiscono dal compilatore al compilatore e anche attraverso diverse versioni dello stesso compilatore.
Ma questo è quello "grosso" avviene nella maggior parte dei casi:
delete
composte da 2 operazioni principali:
- si chiama il distruttore se è definito
- che libera in qualche modo la memoria allocata l'oggetto
Quindi, se il distruttore contiene un codice che accede a qualsiasi dato di classe che è già stato eliminato, potrebbe essere segfau ORA (molto probabilmente) leggerete alcuni dati senza senso. Se questi dati cancellati sono puntatori, molto probabilmente segfault, perché tenterai di accedere alla memoria che contiene qualcos'altro o che non ti appartiene.
Se il costruttore non tocca alcun dato o non è presente (non consideriamo i distruttori virtuali qui per semplicità), potrebbe non essere un motivo di arresto anomalo nella maggior parte delle implementazioni del compilatore. Tuttavia, chiamare un distruttore non è l'unica operazione che sta per accadere qui.
La memoria deve essere liberata. Il modo in cui è fatto dipende dall'implementazione nel compilatore, ma può anche eseguire alcune funzioni simili a free
, dandogli il puntatore e la dimensione del tuo oggetto. Chiamare free
sulla memoria che è stata già eliminata potrebbe bloccarsi, perché la memoria potrebbe non appartenere più a te. Se appartiene a te, potrebbe non bloccarsi immediatamente, ma potrebbe sovrascrivere la memoria già allocata per qualche oggetto diverso del tuo programma.
Ciò significa che una o più delle tue strutture di memoria sono appena state danneggiate e il tuo programma probabilmente si bloccherà prima o poi o potrebbe comportarsi in modo incredibilmente strano. Le ragioni non saranno ovvie nel tuo debugger e potresti passare settimane a capire che diavolo è appena successo.
Quindi, come altri hanno già detto, è in genere una cattiva idea, ma suppongo che tu lo sappia già. Non ti preoccupare, il micio innocente molto probabilmente non morirà se elimini un oggetto due volte.
Ecco esempio di codice che è sbagliato, ma può funzionare bene così (funziona bene con GCC su linux):
class a {};
int main()
{
a *test = new a();
delete test;
a *test2 = new a();
delete test;
return 0;
}
Se non mi crea un'istanza intermedia di quella classe tra eliminazioni, 2 chiamate a liberare sulla stessa memoria avviene come previsto:
*** Error in `./a.out': double free or corruption (fasttop): 0x000000000111a010 ***
per rispondere alle vostre domande direttamente:
Qual è la cosa peggiore che può accadere:
In teoria, il programma causa qualcosa di fatale. Si può anche tentare in modo casuale di cancellare il disco rigido in alcuni casi estremi. Le probabilità dipendono da cosa sia effettivamente il tuo programma (driver del kernel? Programma di spazio utente?).
In pratica, molto probabilmente si bloccherebbe con il segfault. Ma potrebbe accadere qualcosa di peggio.
Il compilatore sta per inviare un errore?
Non dovrebbe.
Sì, può essere importante. No, il compilatore non sta per "lanciare un errore". Semplicemente non farlo :) – paulsm4
Penso che in pratica il peggio che * plausibilmente * possa accadere è che qualche tempo dopo, l'allocatore di memoria si comporta male.Questo (a) ti costringe a impiegare molto tempo a tentare il debug, poiché i sintomi non sono affatto vicini alla causa e inoltre (b) crea una seria vulnerabilità di sicurezza nel software, che il tuo datore di lavoro viene citato in giudizio, perde, fallisce e il tuo contratto finisce per essere di proprietà di un ragazzo di nome Clive che effettua permessi domestici a un prezzo fisso per camion. Ti costringe a lavorare con i tuoi giochi di ruolo sul porno tentacolo giapponese che ti riguardano. –
Non farlo e non farlo mai. È un comportamento indefinito. L'implementazione di C++ può fare qualsiasi cosa in questi casi. Potrebbe davvero fare cose cattive come corrompere il tuo heap, apportare modifiche arbitrarie e bizzarre ad altri oggetti nell'heap e fare anche cose peggiori. Se si usano puntatori grezzi è meglio impostarlo come puntatore nullo dopo la prima cancellazione perché l'eliminazione del puntatore nullo è sicura, altrimenti utilizzare puntatori intelligenti nel C++ moderno. – Destructor