Chiamata di eliminazione sulla variabile allocata nello stack

Ignorando lo stile e il design della programmazione, è “sicuro” chiamare l’eliminazione su una variabile allocata nello stack?

Per esempio:

int nAmount; delete &nAmount; 

o

 class sample { public: sample(); ~sample() { delete &nAmount;} int nAmount; } 

No , non è sicuro chiamare l’ delete su una variabile allocata allo stack. Dovresti chiamare delete su cose create da new .

  • Per ogni malloc o calloc , dovrebbe esserci esattamente uno free .
  • Per ogni new ci dovrebbe essere esattamente una delete .
  • Per ogni new[] dovrebbe esserci esattamente una delete[] .
  • Per ogni allocazione di stack, non dovrebbero esserci liberazioni o cancellazioni esplicite. Il distruttore viene chiamato automaticamente, dove applicabile.

In generale, non è ansible mescolare e abbinare nessuno di questi, ad esempio senza free o delete[] -ing un new object. Ciò comporta un comportamento indefinito.

Bene, proviamo:

 [email protected]:~$ echo 'main() { int a; delete &a; }' > test.cpp [email protected]:~$ g++ -o test test.cpp [email protected]:~$ ./test Segmentation fault 

Quindi a quanto pare non è affatto sicuro.

Tenere presente che quando si assegna un blocco di memoria utilizzando new (o malloc per quella materia), il blocco effettivo della memoria allocata sarà maggiore di quello 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 libero ed eventualmente essere coalizzato con blocchi liberi adiacenti.

Quando provate a liberare memoria che non avete ricevuto da una nuova, le informazioni di contabilità non saranno lì, ma il sistema si comporterà come è e i risultati saranno imprevedibili (di solito cattivi).

Sì, è un comportamento indefinito: passare a delete tutto ciò che non è new è 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 di puntatore null ; in tal caso, e se la funzione deallocazione è fornita nella libreria standard, la chiamata alla funzione deallocazione non ha alcun effetto. Altrimenti, il valore fornito operator delete(void*) nella libreria standard deve essere uno dei valori restituiti da una precedente chiamata di uno dei due operator new(std::size_t) o operator new(std::size_t, const std::nothrow_t&) nella libreria standard.

Le conseguenze di un comportamento indefinito sono, beh, indefinite. “Nulla accade” è una conseguenza valida come qualsiasi altra cosa. Tuttavia, di solito, “nulla accade immediatamente”: la deallocazione di un blocco di memoria non valido può avere gravi conseguenze nelle successive chiamate all’assegnatore.

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

  1. chiamare delete su una variabile stack non sembra fare nulla. Nessun errore, ma posso accedere alla variabile senza problemi dopo la cancellazione.

  2. Avere una class con un metodo con delete this con successo l’object se è allocato nell’heap, ma non se è allocato nello stack (se è nello stack, non accade nulla).

Nessuno può sapere cosa succede. Questo richiama un comportamento indefinito, quindi letteralmente tutto può succedere. Non farlo.

No, la memoria allocata usando il nuovo dovrebbe essere cancellata usando l’operatore delete e quella allocata usando malloc dovrebbe essere cancellata usando free. E non c’è bisogno di deallocare la variabile che sono allocati sullo stack.

Un angelo perde le ali … Puoi solo chiamare delete su un puntatore allocato con new , altrimenti ottieni un comportamento indefinito.

qui la memoria è allocata usando lo stack quindi non c’è bisogno di eliminarlo esternamente ma se si ha una sincronizzazione dynamic

come int * a = new int ()

quindi devi eliminare e non eliminare & a (a sua volta è un puntatore), perché la memoria è allocata dallo store gratuito.

Hai già risposto tu stesso alla domanda. delete deve essere utilizzata solo per i puntatori triggersti ​​tramite new . Fare qualsiasi altra cosa è un comportamento indefinito semplice e semplice.

Quindi non c’è davvero alcun modo di dire cosa succede, qualsiasi cosa, dal codice che funziona bene attraverso il crashing per cancellare il tuo hard disk, è un risultato valido per farlo. Quindi per favore non farlo mai .

È UB perché non devi chiamare delete su un object che non è stato allocato dynamicmente con new. È così semplice.