Konteks: Saya mencoba memahami petunjuk, kami baru saja melihatnya beberapa minggu yang lalu di sekolah dan saat berlatih hari ini saya bertemu dengan orang bodoh? masalah, ini bisa sangat mudah bagi Anda tetapi saya memiliki sedikit atau tidak ada pengalaman pemrograman.
Saya telah melihat beberapa pertanyaan di SO tentang menghapus pointer tetapi semuanya tampaknya terkait dengan menghapus kelas dan bukan pointer 'sederhana' (atau apa pun istilah yang tepat), inilah kode yang saya coba Lari:
#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.
}
Jadi pertanyaan saya adalah:
- Mengapa kasus pertama tidak berhasil? Tampaknya penggunaan paling mudah untuk menggunakan dan menghapus penunjuk? Kesalahan mengatakan memori tidak dialokasikan tetapi 'cout' mengembalikan alamat.
- Pada contoh kedua kesalahan tidak dipicu tetapi melakukan cout nilai myPointer masih mengembalikan alamat memori?
- Apakah # 3 benar-benar berfungsi? Sepertinya berhasil bagi saya, penunjuk tidak lagi menyimpan alamat, apakah ini cara yang tepat untuk menghapus penunjuk?
Maaf untuk pertanyaan yang panjang, ingin membuatnya sejelas mungkin, juga untuk menegaskan kembali, saya memiliki sedikit pengalaman pemrograman, jadi jika seseorang dapat menjawab ini menggunakan istilah awam, itu akan sangat dihargai!
sumber
delete
apa kamunew
. Itu juga tidak diperlukan untuk pointer untuk mengatur dirinya sendiri ke NULL setelah Anda menghapusnya. Jika Anda menginginkan keamanan di sana, gunakan penunjuk cerdas, yang membebaskan memori untuk Anda dan memberikan kesalahan saat Anda mencoba mengaksesnya ketika tidak ada sesuatu.reset
dan membebaskan yang lama. Untuk membebaskannya tanpa penggantian, Anda meneleponrelease
. Ketika keluar dari ruang lingkup, itu dihancurkan, dan dapat membebaskan memori berdasarkan jenisnya.std::unique_ptr
dimaksudkan hanya untuk satu pemilik.std::shared_ptr
membebaskannya saat pemilik terakhir berhenti memiliki sumber daya. Mereka juga aman untuk pengecualian. Jika Anda mengalokasikan sumber daya dengan satu sumber daya, lalu menemukan pengecualian, sumber daya tersebut akan dibebaskan dengan benar.Jawaban:
1 & 2
myVar = 8; //not dynamically allocated. Can't call delete on it. myPointer = new int; //dynamically allocated, can call delete on it.
Variabel pertama dialokasikan di tumpukan. Anda hanya dapat memanggil delete pada memori yang Anda alokasikan secara dinamis (di heap) menggunakan
new
operator.3.
myPointer = NULL; delete myPointer;
Di atas tidak melakukan apa pun . Anda tidak membebaskan apa pun, karena penunjuk menunjuk ke NULL.
Hal berikut tidak boleh dilakukan:
myPointer = new int; myPointer = NULL; //leaked memory, no pointer to above int delete myPointer; //no point at all
Anda mengarahkannya ke NULL, meninggalkan memori yang bocor (int baru yang Anda alokasikan). Anda harus membebaskan memori yang Anda tunjuk. Tidak ada cara untuk mengakses yang dialokasikan
new int
lagi, karena itu kebocoran memori.Cara yang benar:
myPointer = new int; delete myPointer; //freed memory myPointer = NULL; //pointed dangling ptr to NULL
Cara yang lebih baik:
Jika Anda menggunakan C ++, jangan gunakan pointer mentah. Gunakan petunjuk cerdas sebagai gantinya yang dapat menangani hal-hal ini untuk Anda dengan sedikit biaya tambahan. C ++ 11 hadir dengan beberapa .
sumber
delete myPointer
deallocates*myPointer
. Itu betul. NamunmyPointer
tetap menunjuk pada lokasi memori yang sudah dibebaskan dan tidak boleh digunakan karena di UB. Ini tidak akan dapat diakses setelah akhir lingkup hanya JIKA itu adalah variabel lokal di tempat pertama.new
setiap hari. (Saya murahan!)NULL
mencegah kami menyalahgunakannya nanti.Saya yakin Anda tidak sepenuhnya memahami cara kerja pointer.
Ketika Anda memiliki penunjuk yang menunjuk ke beberapa memori, ada tiga hal berbeda yang harus Anda pahami:
- ada "apa yang ditunjukkan" oleh penunjuk (memori)
- alamat memori ini
- tidak semua penunjuk harus memiliki memori yang dihapus: Anda hanya perlu menghapus memori yang dialokasikan secara dinamis (
new
operator bekas ).Membayangkan:
int *ptr = new int; // ptr has the address of the memory. // at this point, the actual memory doesn't have anything. *ptr = 8; // you're assigning the integer 8 into that memory. delete ptr; // you are only deleting the memory. // at this point the pointer still has the same memory address (as you could // notice from your 2nd test) but what inside that memory is gone!
Saat Anda melakukannya
ptr = NULL; // you didn't delete the memory // you're only saying that this pointer is now pointing to "nowhere". // the memory that was pointed by this pointer is now lost.
C ++ memungkinkan Anda mencoba
delete
penunjuk yang menunjuknull
tetapi tidak benar-benar melakukan apa pun, hanya tidak memberikan kesalahan apa pun.sumber
Pointer mirip dengan variabel normal karena Anda tidak perlu menghapusnya. Mereka dihapus dari memori pada akhir pelaksanaan fungsi dan / atau akhir program.
Namun Anda dapat menggunakan pointer untuk mengalokasikan 'blok' memori, misalnya seperti ini:
int *some_integers = new int[20000]
Ini akan mengalokasikan ruang memori untuk 20000 integer. Berguna, karena Stack memiliki ukuran yang terbatas dan Anda mungkin ingin mengotak-atik muatan 'int' yang besar tanpa kesalahan stack overflow.
Setiap kali Anda memanggil baru, Anda harus 'menghapus' di akhir program Anda, karena jika tidak, Anda akan mendapatkan kebocoran memori, dan beberapa ruang memori yang dialokasikan tidak akan pernah dikembalikan untuk digunakan oleh program lain. Untuk melakukan ini:
delete [] some_integers;
Semoga membantu.
sumber
baru tidak pernah dipanggil. Jadi alamat yang dicetak cout adalah alamat lokasi memori myVar, atau nilai yang diberikan ke myPointer dalam kasus ini. Dengan menulis:
kamu bilang:
Ini mengembalikan alamat yang menunjuk ke lokasi memori yang telah dihapus. Karena pertama Anda membuat pointer dan menetapkan nilainya ke myPointer, kedua Anda menghapusnya, ketiga Anda mencetaknya. Jadi, kecuali Anda memberikan nilai lain ke myPointer, alamat yang dihapus akan tetap ada.
NULL sama dengan 0, Anda menghapus 0, jadi Anda tidak menghapus apa pun. Dan logikanya mencetak 0 karena Anda melakukannya:
myPointer = NULL;
yang sama dengan:
myPointer = 0;
sumber
sumber
int value, *ptr; value = 8; ptr = &value; // ptr points to value, which lives on a stack frame. // you are not responsible for managing its lifetime. ptr = new int; delete ptr; // yes this is the normal way to manage the lifetime of // dynamically allocated memory, you new'ed it, you delete it. ptr = nullptr; delete ptr; // this is illogical, essentially you are saying delete nothing.
sumber