Chamando delete na variável alocada na pilha

Ignorando estilo de programação e design, é “seguro” chamar delete em uma variável alocada na pilha?

Por exemplo:

int nAmount; delete &nAmount; 

ou

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

Não , não é seguro chamar delete em uma variável alocada em pilha. Você só deve chamar delete em coisas criadas por new .

  • Para cada malloc ou calloc , deve haver exatamente um free .
  • Para cada new , deve haver exatamente uma delete .
  • Para cada new[] , deve haver exatamente uma delete[] .
  • Para cada alocação de pilha, não deve haver liberação ou exclusão explícita. O destruidor é chamado automaticamente, quando aplicável.

Em geral, você não pode misturar e combinar nada disso, por exemplo, sem free ou delete[] um new object. Fazer isso resulta em comportamento indefinido.

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ê aloca um bloco de memory usando o novo (ou malloc para esse assunto), o bloco real de memory alocada será maior do que o que você pediu. O bloco de memory também conterá algumas informações contábeis para que, quando você liberar o bloco, ele possa ser facilmente colocado de volta na piscina livre e, possivelmente, ser coalhado com blocos livres adjacentes.

Quando você tenta liberar qualquer memory que você não tenha recebido de novo, essa informação contábil não estará lá, mas o sistema agirá como está e os resultados serão imprevisíveis (geralmente ruins).

Sim, é um comportamento indefinido: passar para delete tudo que não veio de new é UB:

Padrão C ++, seção 3.7.3.2.3: O valor do primeiro argumento fornecido para uma das funções de desalocação fornecidas na biblioteca padrão pode ser um valor de ponteiro null ; se assim for, e se a function de desalocação for uma fornecida na biblioteca padrão, a chamada para a function de desalocação não terá efeito. Caso contrário, o valor fornecido ao operator delete(void*) na biblioteca padrão deve ser um dos valores retornados por uma invocação anterior de um operator new(std::size_t) ou operator new(std::size_t, const std::nothrow_t&) na biblioteca padrão.

As consequências do comportamento indefinido são, bem, indefinidas. “Nada acontece” é uma conseqüência tão válida quanto qualquer outra coisa. No entanto, geralmente “nada acontece imediatamente”: desalocar um bloco de memory inválido pode ter consequências graves em chamadas subsequentes para o alocador.

Depois de jogar um pouco com o g + + 4.4 no windows, obtive resultados muito interessantes:

  1. chamar delete em uma variável de pilha não parece fazer nada. Nenhum erro é lançado, mas posso acessar a variável sem problemas após a exclusão.

  2. Ter uma class com um método com delete this exclui com êxito o object se ele estiver alocado no heap, mas não se estiver alocado na pilha (se estiver na pilha, nada acontece).

Ninguém pode saber o que acontece. Isso invoca um comportamento indefinido, então, literalmente, tudo pode acontecer. Não faça isso.

Não, A memory alocada usando o novo deve ser excluída usando o operador delete e o alocado usando malloc deve ser excluído usando free. E não há necessidade de desalocar a variável que está alocada na pilha.

Um anjo perde suas asas … Você só pode chamar delete em um ponteiro alocado com o new , caso contrário, você obtém um comportamento indefinido.

aqui a memory é alocada usando a pilha, então não é necessário excluí-la externamente, mas se você tiver alocado dinamicamente

como int * a = new int ()

então você tem que fazer delete a e não delete & a (a própria é um ponteiro), porque a memory é alocada a partir da free store.

Você já respondeu a pergunta você mesmo. delete só deve ser usado para pointers optados por new . Fazer qualquer outra coisa é um comportamento simples e indefinido.

Portanto, não há como dizer o que acontece, qualquer coisa, desde o código funcionando bem até o apagamento do disco rígido, é um resultado válido de se fazer isso. Então, por favor, nunca faça isso .

É UB porque você não deve chamar delete em um item que não tenha sido alocado dinamicamente com new. É simples assim.