Perché non dovrei provare ad usare “questo” valore dopo “cancellare questo”?

StackOverflow https://stackoverflow.com/questions/1866461

  •  18-09-2019
  •  | 
  •  

Domanda

questo paragrafo di utilizzo C ++ FAQ di delete this costrutto è discusso. 4 restrizioni sono elencati.

Restrizioni 1 a 3 sembrano abbastanza ragionevole. Ma perché è Restrizione 4 là che io "non devo esaminarla, confrontarlo con un altro puntatore, confrontarlo con NULL, stamparlo, cast, fare qualsiasi cosa con esso"?

Voglio dire this è ancora un altro puntatore. Perché non posso reinterpret_cast a un int o chiamare printf() per emettere il suo valore?

È stato utile?

Soluzione

La ragione per cui non si può fare qualsiasi cosa con un puntatore dopo averlo eliminato (questo, o qualsiasi altro puntatore), è che l'hardware potrebbe (e alcune macchine più vecchie hanno fatto) trappola cercando di caricare un indirizzo di memoria non valida in un registro. Anche se può andare bene su tutto l'hardware moderno, lo standard dice che l'unica cosa che si può fare ad un puntatore non valido (non inizializzato o eliminato), è di assegnare ad essa (o NULL, o da un altro puntatore valido).

Altri suggerimenti

Il valore di 'questo' dopo aver chiamato cancellare non è definito, e il comportamento di tutto ciò che fate con esso è anche definito. Mentre mi aspetterei maggior parte dei compilatori di fare qualcosa di sensato, non c'è niente (nelle specifiche) fermare il compilatore di decidere che il suo comportamento in questo caso specifico sarà emette codice per formattare il disco rigido. Invocare comportamento non definito è (quasi) sempre un errore, anche quando il compilatore particolare si comporta nel modo che desideri a.

Si potrebbe ovviare a questo prendendo una copia del puntatore (come un numero intero) prima di chiamare cancellare.

Aha!

3.7.3.2/4:." ... la funzione deallocazione dovrà rilasciare l'archiviazione a cui fa riferimento il puntatore, rendendo non validi tutti i puntatori che si riferiscono a qualsiasi parte dello stoccaggio deallocato L'effetto di utilizzare un valore di puntatore non valido (compresi passandogli a una funzione deallocazione) è indefinito".

Si noti che questo dice "con il valore", non "dereferenziazione il puntatore".

Questo paragrafo non è specifico per this, si applica a tutto ciò che è stato eliminato.

perché ogni azione che si può prendere con quel puntatore potrebbe innescare la logica che viene interpretato sui metodi di classe di quell'oggetto, che potrebbe portare ad un crash.

Ora, alcune delle azioni che si punta potrebbe essere apparentemente "sicuri", ma è difficile dire che cosa accade all'interno di qualsiasi metodo che si può chiamare.

da posta:? "Non deve esaminarlo, confrontarlo con un altro puntatore, confrontarlo con NULL, stamparlo, cast, fare qualsiasi cosa con esso"

Tutte queste azioni possono attivare le funzioni relative operatore, che vengono valutati con un puntatore non definito. Idem per la fusione.

Ora, se si esegue un reintepret_cast, che probabilmente è una storia diversa, e probabilmente si potrebbe ottenere con esso, come cr è solo un po 'alla reinterpretazione, senza coinvolgere (per quanto ne so) qualsiasi chiamata di metodo.

Per lo stesso motivo non sarebbe eliminare qualsiasi altro puntatore e poi cercare di eseguire operazioni su di esso.

b / c l'indirizzo che ciò si riferisce ad ora, non definita, e non si sa cosa potrebbe essere lì ...

In un programma multi-thread, nel momento in cui delete un puntatore, lo spazio libero possono essere assegnati da un altro thread, sovrascrivendo lo spazio utilizzato da this. Anche in un programma di single-thread, a meno che non sei molto attenti a quello che si chiama prima returning, qualsiasi cosa si fa dopo delete this potrebbe allocare la memoria e sovrascrivere quello usato per essere puntato da this.

In un Microsoft Visual C ++ eseguibile compilato in modalità debug, deleteing un puntatore provoca la sua memoria per essere immediatamente sovrascritto con un modello di prova 0xCC (variabili non inizializzate sono inizializzati con questo modello), per aiutare a identificare penzoloni bug puntatore come questa uno.

Questo mi ricorda di quando ho fissato un bug in un gioco online giocabile in cui il costruttore di un oggetto di fuoco eliminato il più antico del fuoco se il numero totale degli incendi aveva raggiunto un certo numero. The Fire cancellato era a volte il fuoco genitore creazione di un nuovo Fire - BAM, penzoloni puntatore bug! E 'stato solo grazie alla fortuna che questo bug ha interagito con l'algoritmo di allocazione di memoria in modo del tutto prevedibile (il Fuoco cancellato era sempre sovrascritto con un nuovo fuoco nello stesso modo) - altrimenti sarebbe causato una desincronizzazione tra i giocatori online. Ho trovato questo bug quando riscrivere il modo in cui il gioco ha fatto di allocazione della memoria. Grazie alla sua prevedibilità, quando ho riparato, sono stato anche in grado di implementare l'emulazione del suo comportamento per la compatibilità con i client di gioco più anziani.

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