Contexto: Estou tentando entender os ponteiros, acabamos de vê-los há algumas semanas na escola e enquanto praticava hoje encontrei um idiota? problema, pode ser super simples para você, mas tenho pouca ou nenhuma experiência em programação.
Já vi algumas perguntas no SO sobre a exclusão de ponteiros, mas todas parecem estar relacionadas à exclusão de uma classe e não a um ponteiro "simples" (ou qualquer que seja o termo adequado), aqui está o código que estou tentando corre:
#include <iostream>;
using namespace std;
int main() {
int myVar,
*myPointer;
myVar = 8;
myPointer = &myVar;
cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;
// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6
// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.
// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.
}
Então, minhas perguntas são:
- Por que o primeiro caso não funciona? Parece o uso mais simples de usar e excluir um ponteiro? O erro diz que a memória não foi alocada, mas 'cout' retornou um endereço.
- No segundo exemplo o erro não está sendo disparado mas fazer um cout do valor de myPointer ainda retorna um endereço de memória?
- # 3 realmente funciona? Parece que funciona, o ponteiro não está mais armazenando um endereço. Essa é a maneira correta de excluir um ponteiro?
Desculpe pela longa pergunta, queria deixar isso o mais claro possível, também para reiterar, eu tenho pouca experiência em programação, então se alguém pudesse responder usando termos leigos, ficaria muito grato!
c++
pointers
delete-operator
leópico
fonte
fonte
delete
que vocênew
. Também não é necessário que o ponteiro se defina como NULL após você excluí-lo. Se você quiser segurança aí, use smart pointers, que liberam a memória para você e dão erros quando você tenta acessá-los quando não estão segurando algo.reset
e libera o antigo. Para liberar sem reposição, você ligarelease
. Quando sai do escopo, é destruído e pode liberar a memória com base no tipo que é.std::unique_ptr
destina-se a apenas um proprietário.std::shared_ptr
libera-o quando o último proprietário deixa de possuir o recurso. Eles também são seguros contra exceções. Se você alocar um recurso com um e, em seguida, encontrar uma exceção, o recurso será liberado corretamente.Respostas:
1 e 2
A primeira variável foi alocada na pilha. Você pode chamar delete apenas na memória alocada dinamicamente (no heap) usando o
new
operador.3 -
O acima exposto não fez nada . Você não liberou nada, pois o ponteiro apontava para NULL.
O seguinte não deve ser feito:
Você o apontou para NULL, deixando para trás memória perdida (o novo int que você alocou). Você deve liberar a memória para a qual estava apontando. Não há mais como acessar aquele alocado
new int
, daí vazamento de memória.Da maneira correta:
A melhor maneira:
Se você estiver usando C ++, não use ponteiros brutos. Em vez disso, use ponteiros inteligentes, que podem lidar com essas coisas para você com pouca sobrecarga. C ++ 11 vem com vários .
fonte
delete myPointer
desaloca*myPointer
. Está correto. MasmyPointer
continua a apontar para um local de memória que foi liberado e não deve ser usado porque é UB. Ela ficará inacessível após o fim do escopo apenas SE for uma variável local em primeiro lugar.new
todos os dias. (Eu sou cafona!)NULL
evita que o façamos mal posteriormente.Eu acredito que você não está entendendo totalmente como os ponteiros funcionam.
Quando você tem um ponteiro apontando para alguma memória, há três coisas diferentes que você deve entender:
- há "o que é apontado" pelo ponteiro (a memória)
- este endereço de memória
- nem todos os ponteiros precisam ter sua memória excluída: apenas você precisa excluir a memória que foi alocada dinamicamente (
new
operador usado ).Imagine:
Quando você fez
C ++ permite que você tente
delete
um ponteiro que aponta para,null
mas na verdade não faz nada, apenas não dá nenhum erro.fonte
Os ponteiros são semelhantes às variáveis normais no sentido de que você não precisa excluí-los. Eles são removidos da memória no final da execução de uma função e / ou no final do programa.
No entanto, você pode usar ponteiros para alocar um 'bloco' de memória, por exemplo:
Isso alocará espaço de memória para 20.000 inteiros. Útil, porque a pilha tem um tamanho limitado e você pode querer mexer com uma grande carga de 'ints' sem um erro de estouro de pilha.
Sempre que você chamar new, você deve então 'deletar' no final do seu programa, porque caso contrário, você terá um vazamento de memória e algum espaço de memória alocado nunca será retornado para outros programas usarem. Para fazer isso:
Espero que ajude.
fonte
novo nunca é chamado. Portanto, o endereço que cout imprime é o endereço da localização da memória de myVar, ou o valor atribuído a myPointer neste caso. Por escrito:
você diz:
Ele retorna um endereço que aponta para um local da memória que foi excluído. Porque primeiro você cria o ponteiro e atribui seu valor a myPointer, segundo você o exclui, terceiro você o imprime. Portanto, a menos que você atribua outro valor a myPointer, o endereço excluído permanecerá.
NULL é igual a 0, você exclui 0, portanto, não exclui nada. E é lógico que ele imprima 0 porque você:
que é igual a:
fonte
fonte
fonte