Domanda

Ignorando lo stile e il design della programmazione, è "sicuro"? chiamare delete su una variabile allocata nello stack?

Ad esempio:

   int nAmount;
   delete &nAmount;

o

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
È stato utile?

Soluzione

No , non lo è sicuro di chiamare delete su una variabile allocata in pila. Dovresti chiamare delete solo su cose create da new .

  • Per ogni malloc o calloc , dovrebbe esserci esattamente un gratuito .
  • Per ogni nuovo dovrebbe esserci esattamente un elimina .
  • Per ogni nuovo [] dovrebbe esserci esattamente un delete [] .
  • Per ogni allocazione di stack, non ci dovrebbero essere liberazioni o cancellazioni esplicite. Il distruttore viene chiamato automaticamente, ove applicabile.

In generale, non puoi mescolare e abbinare nessuno di questi, ad es. nessun libero -ing o elimina [] -ing un oggetto nuovo . Ciò comporta un comportamento indefinito.

Altri suggerimenti

Bene, proviamolo:

jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault

Quindi apparentemente non è affatto sicuro.

Tieni presente che quando assegni un blocco di memoria usando new (o malloc per quella materia), l'effettivo blocco di memoria allocato sarà più grande di quello che hai richiesto. Il blocco di memoria conterrà anche alcune informazioni di contabilità in modo che quando si libera il blocco, può essere facilmente reinserito nel pool gratuito e possibilmente essere coalizzato con blocchi liberi adiacenti.

Quando provi a liberare memoria che non hai ricevuto da nuovi, le informazioni di contabilità non saranno presenti ma il sistema agirà come è e i risultati saranno imprevedibili (di solito cattivi).

Sì, è un comportamento indefinito: passare a elimina tutto ciò che non proviene da nuovo è UB:

  

Standard C ++, sezione 3.7.3.2.3:   Il valore del primo argomento fornito a una delle funzioni di deallocazione fornite nella libreria standard può essere un valore puntatore null ; in tal caso e se la funzione di deallocazione viene fornita nella libreria standard, la chiamata alla funzione di deallocazione non ha alcun effetto. Altrimenti, il valore fornito a operator delete (void *) nella libreria standard deve essere uno dei valori restituiti da una precedente invocazione di operator new (std :: size_t) o operatore new (std :: size_t, const std :: nothrow_t & amp;) nella libreria standard.

Le conseguenze di comportamenti indefiniti sono, beh, indefinite. " Non succede nulla " è una conseguenza valida come qualsiasi altra cosa. Tuttavia, di solito "non succede nulla subito": la deallocazione di un blocco di memoria non valido può avere gravi conseguenze nelle successive chiamate all'allocatore.

Dopo aver giocato un po 'con g ++ 4.4 in Windows, ho ottenuto risultati molto interessanti:

  1. la chiamata di eliminazione su una variabile dello stack non sembra fare nulla. Non vengono generati errori, ma dopo la cancellazione posso accedere alla variabile senza problemi.

  2. Avere una classe con un metodo con elimina questo elimina correttamente l'oggetto se è allocato nell'heap, ma non se è allocato nello stack (se è nello stack , non succede nulla).

Nessuno può sapere cosa succede. Ciò invoca comportamenti indefiniti, quindi letteralmente può succedere di tutto. Non farlo.

No, La memoria allocata usando new dovrebbe essere cancellata usando l'operatore delete e quello allocato usando malloc dovrebbe essere eliminato usando free. E non è necessario deallocare la variabile allocata nello stack.

Un angelo perde le ali ... Puoi chiamare elimina su un puntatore assegnato con nuovo , altrimenti otterrai un comportamento indefinito.

qui la memoria viene allocata usando lo stack, quindi non è necessario eliminarla esternamente ma se si è allocato dinamicamente

come int * a = new int ()

quindi devi eliminare a e non eliminare & amp; a (a stesso è un puntatore), perché la memoria viene allocata dall'archivio libero.

Hai già risposto tu stesso alla domanda. delete deve essere utilizzato solo per i puntatori ottenuti tramite new . Fare qualsiasi altra cosa è un comportamento chiaramente definito e semplice.

Quindi non si può davvero dire cosa succede, qualsiasi cosa, dal codice che funziona bene attraverso l'arresto anomalo alla cancellazione del disco rigido, è un risultato valido nel fare ciò. Quindi per favore non farlo mai .

È UB perché non è necessario chiamare delete su un elemento che non è stato allocato dinamicamente con new. È così semplice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top