Pergunta

No este ponto de C++ FAQ o uso de delete this construir é discutido.4 restrições são listados.

Restrições de 1 a 3 parecem bastante razoáveis.Mas porque é que a restrição 4 lá que eu "não deve examiná-lo, compará-lo com outro ponteiro, compará-la com NULL, imprimi-lo, lançá-lo, fazer qualquer coisa com ele"?

Eu quero dizer this é ainda um outro ponteiro.Por que eu não posso reinterpret_cast para um int ou ligue para printf() para a saída de seu valor?

Foi útil?

Solução

A razão pela qual você não pode fazer nada com um ponteiro depois de excluí -lo (esta ou qualquer outro ponteiro) é que o hardware poderia (e algumas máquinas mais antigas fizeram) a armadilha tentando carregar um endereço de memória inválido em um registro. Embora possa estar bem em todo o hardware moderno, o padrão diz que a única coisa que você pode fazer para um ponteiro inválido (não inicializado ou excluído) é atribuir a ele (nulo ou de outro ponteiro válido).

Outras dicas

O valor de 'isto' depois de ligar para excluir é indefinido, e o comportamento de qualquer coisa que você faça com ele também é indefinido. Embora eu esperasse que a maioria dos compiladores fizesse algo sensata, não há nada (na especificação) impedindo que o compilador decidisse que seu comportamento nesse caso em particular será emitido código para formatar seu disco rígido. Invocar o comportamento indefinido é (quase) sempre um erro, mesmo quando seu compilador em particular se comporta da maneira que você gostaria.

Você pode contornar isso pegando uma cópia do ponteiro (como um número inteiro) antes de ligar para excluir.

AHA!

3.7.3.2/4: "... A função de desalocação deve desalocar o armazenamento referenciado pelo ponteiro, tornando inválido todos os ponteiros referentes a qualquer parte do armazenamento desalocado. função) é indefinido ".

Observe que isso diz "usando o valor", não "desreferenciando o ponteiro".

Esse parágrafo não é específico para this, isso se aplica a qualquer coisa que tenha sido excluída.

Porque qualquer ação que você possa tomar com esse ponteiro pode acionar a lógica que é interpretada nos métodos de classe desse objeto, o que pode levar a uma falha.

Agora, algumas das ações que você aponta podem ser aparentemente "seguras", mas é difícil dizer o que acontece em qualquer método que você possa ligar.

A partir do post: "Não deve examiná -lo, compará -lo com outro ponteiro, compará -lo com nulo, imprimi -lo, lançá -lo, fazer qualquer coisa com ele"?

Todas essas ações podem desencadear funções relacionadas ao operador, que são avaliadas com um ponteiro indefinido. Idem para elenco.

Agora, se você executar um reintet_cast, essa é provavelmente uma história diferente, e você provavelmente poderá se dar bem com ela, pois reinterprete é um pouco a pouco a reinterpretação, sem envolver (até onde eu sei) nenhuma chamada de método.

Pelo mesmo motivo, você não excluiria nenhum outro ponteiro e tentaria executar quaisquer operações nele.

b/c o endereço que isso se refere agora, indefinido, e você não sabe o que pode estar lá ...

Em um programa multi-threaded, o momento em que você delete um ponteiro, o espaço livre pode ser atribuído por outra thread, a substituição do espaço utilizado pelo this.Mesmo em um segmento único programa, a menos que você é muito cuidadoso sobre o que você chama de antes returning, qualquer coisa que você faz depois de delete this poderia alocar memória e substituir o que costumava ser apontado pelo this.

Em um Microsoft Visual C++ executável compilado em modo de Depuração, deleteing um ponteiro faz com que a sua memória para ser imediatamente substituído com um 0xCC padrão de teste (variáveis não inicializadas são também inicializados com este padrão), para ajudar na identificação de oscilação do ponteiro erros como este.

Isso me lembra de quando eu corrigido um bug em um online jogável jogo em que um Incêndio construtor do objecto eliminado o mais antigo de Incêndio se o número total de Fogos, tinha alcançado um determinado número.O Fogo foi apagado, por vezes, o pai do Fogo, criando um novo Fogo — bam, de oscilação do ponteiro do bug!Foi apenas devido à sorte que este erro interagiram com o algoritmo de alocação de memória em um completamente de maneira previsível (excluído Incêndio foi sempre substituído por um novo Incêndio no mesmo caminho) — caso contrário, teria causado uma dessincronização entre os jogadores online.Eu descobri este bug quando reescrever a forma como o jogo fez a alocação de memória.Devido à sua previsibilidade, quando eu fixo ele, eu também era capaz de implementar a emulação de seu comportamento para a compatibilidade com os jogos mais antigos clientes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top