Chamando de exclusão na variável alocada na pilha
-
22-07-2019 - |
Pergunta
Ignorando estilo de programação e design, é "seguro" para chamar de eliminação num variável alocada na pilha?
Por exemplo:
int nAmount;
delete &nAmount;
ou
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
Solução
Sem , não é seguro para chamar delete
em uma variável alocada-stack. Você só deve chamar delete
em coisas criadas por new
.
- Para cada
malloc
oucalloc
, deve haver exatamente umfree
. - Para cada
new
deve haver exatamente umdelete
. - Para cada
new[]
deve haver exatamente umdelete[]
. - Para cada alocação de pilha, não deve haver liberação explícita ou exclusão. O destruidor é chamado automaticamente, quando aplicável.
Em geral, você não pode misturar e combinar qualquer um destes, por exemplo, não free
-ing ou delete[]
-ing um objecto new
. Fazer isso resulta em um comportamento indefinido.
Outras dicas
Bem, vamos tentar:
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
Então, aparentemente não é seguro em tudo.
Tenha em mente que quando você alocar um bloco de memória usando novo (ou malloc para que o assunto), o bloco real de memória alocada será maior do que o que você pediu. O bloco de memória também vai conter algumas informações de contabilidade para que quando você liberar o bloco, ele pode facilmente ser colocado de volta para a piscina livre e, possivelmente, ser fundiram com blocos livres adjacentes.
Quando você tentar libertar qualquer memória que você não recebe de novo, que a informação da contabilidade não vai estar lá, mas o sistema irá agir como ele é e os resultados vão ser imprevisível (geralmente ruim).
Sim, é um comportamento indefinido: passando para delete
qualquer coisa que não veio de new
é UB:
padrão C ++, seção 3.7.3.2.3: O valor do primeiro argumento fornecido a uma das funções Thea desalocação fornecidos na biblioteca padrão pode ser um valor de ponteiro
null
; Se assim for, e se a função de desalocação é fornecido na biblioteca padrão, a chamada para a função de desalocação não tem efeito. Caso contrário, o valor fornecido paraoperator delete(void*)
na biblioteca padrão deve ser um dos valores devolvidos por uma chamada anterior de qualqueroperator new(std::size_t)
ouoperator new(std::size_t, const std::nothrow_t&)
na biblioteca padrão.
As consequências de um comportamento indefinido são, bem, indefinido. "Nada acontece" é como consequência uma válida quanto qualquer outra coisa. No entanto, normalmente é "nada acontece imediatamente":. Desalocá um bloco de memória inválido pode ter consequências graves em chamadas subseqüentes para o alocador
Depois de jogar um pouco com g ++ 4.4 no Windows, eu tenho resultados muito interessantes:
-
chamando de exclusão em um variável de pilha não parece fazer nada. Sem erros jogar, mas eu posso acessar a variável sem problemas após a exclusão.
-
Ter uma classe com um método com
delete this
elimina com sucesso o objeto se ele é alocado no heap, mas não se isso é alocado na pilha (se é na pilha, nada acontece).
Ninguém pode saber o que acontece. Isso invoca um comportamento indefinido, então literalmente qualquer coisa pode acontecer. Não faça isso.
Não, Memória alocada usando novo deve ser eliminada utilizando operador delete e que alocado usando malloc devem ser excluídos usando livre. E não há necessidade de desalocar a variável que são alocados na pilha.
Um anjo perde suas asas ... Você só pode chamar delete
em um ponteiro alocado com new
, caso contrário, você obtém um comportamento indefinido.
aqui a memória é alocada usando pilha assim não há necessidade para excluí-lo exernally mas se você tiver allcoted dinamicamente
como int * a = new int ()
então você tem que fazer apagar um e não excluir e um (a si mesmo é um ponteiro), porque a memória é alocada de loja livre.
Você já respondeu a pergunta a si mesmo. delete
só deve ser usado para ponteiros optained através new
. Fazer qualquer outra coisa é um comportamento indefinido pura e simples.
Portanto, não há realmente nenhuma dizendo o que acontece, qualquer coisa, desde a multa de trabalho de código através de cair para apagar seu disco rígido é um resultado válido de fazer isso. Então, por favor não fazer isso .
UB é porque você não deve chamar de exclusão em um item que não foi alocada dinamicamente com o novo. É simples assim.