Apakah alamat memori di heap dapat digunakan kembali?

Penjelasan lebih lanjut dari judul pertanyaannya adalah, izinkan saya menjelaskan skenario saya.

Saya memiliki wadah daftar penunjuk ke beberapa objek di heap. Setiap kali suatu objek baru dibuat, penunjuknya akan ditambahkan ke daftar dan setiap kali suatu objek dihapus, penunjuknya akan dihapus. Dapat dikatakan bahwa semua petunjuk dalam daftar ini selalu valid.

Banyak objek dalam daftar berisi petunjuk ke objek lain dalam daftar yang sama.

Sebelum saya melakukan dereferensi salah satu dari petunjuk tersebut, saya ingin menggunakan fungsi CheckAgainstList(ptr*) untuk memastikan bahwa satu objek menunjuk ke objek lain dalam daftar yang sama dan oleh karena itu tidak menunjuk ke objek yang telah dihapus.

Pakailah topi kertas timah Anda sekarang, Apakah ini mungkin?

  1. Objek A memiliki pointer ke objek B dengan alamat memori 0x00988e50.
  2. Objek B dihapus.
  3. Objek C dibuat dan ditempatkan ke dalam ruang memori yang baru dibebaskan 0x00988e50.
  4. CheckAgainstList(ptr*) mengembalikan nilai true ketika kita memeriksa pointer karena objek C ada dalam daftar dan berada di alamat memori yang sama dengan yang digunakan B.

Sekarang kita mempunyai bug karena A mengira ia mempunyai penunjuk ke B, namun B hilang dan C bisa dikatakan menggantikannya.

Apakah potensi bug ini mungkin terjadi?


person user1438585    schedule 22.06.2012    source sumber
comment
Bukan hanya mungkin - kemungkinan besar terjadi. Jika Anda membebaskan B dan mengalokasikan C tepat setelahnya, kemungkinan besar dengan banyak implementasi heap Anda akan mendapatkan buffer yang sama segera kembali.   -  person Rafael Baptista    schedule 22.06.2012
comment
Datang ke sini mencari tahu seberapa sering hal ini terjadi, setelah melihat potongan memori jelas digunakan kembali (untuk data dengan tipe yang sama). Jadi iya :)   -  person mlvljr    schedule 27.01.2016


Jawaban (5)


Bukan hanya mungkin, namun sangat mungkin terjadi. Pengalokasi memori yang baik akan mencoba menggunakan kembali memori sesering mungkin untuk mengurangi fragmentasi dan penggembungan.

Masalah yang Anda coba selesaikan mungkin dapat diterima oleh weak_ptr, yang dapat diperiksa validitasnya sebelum itu digunakan.

person Mark Ransom    schedule 22.06.2012

Ya, bug itu sangat mungkin terjadi.

Pada dasarnya apa yang Anda lakukan cukup berbahaya dan akan menyebabkan bug dengan cepat. Anda mungkin sebaiknya menggunakan referensi yang dihitung sebagai ptr pintar. C++11 menyertakan std::shared_ptr yang berarti Anda dapat menggunakannya sebagai pengganti penunjuk normal Anda. Dengan cara ini memori tidak akan terbebas sampai semuanya selesai dan akan mengatasi masalah seperti yang Anda jelaskan.

Satu-satunya pilihan Anda yang lain adalah memindai semua objek lain untuk melihat apakah objek tersebut mereferensikan 'B' yang dihapus dan melakukan sesuatu seperti "null" dari penunjuknya ke penunjuk, yang sekarang telah dihapus.

person Goz    schedule 22.06.2012

Alamat memori dapat digunakan kembali - tergantung pada sistem operasinya. Jika tidak, jika suatu program melakukan banyak alokasi dan dealokasi, lebih dari jumlah RAM di mesin, maka program tersebut tidak akan dapat dilanjutkan.

Pada akhirnya jawabannya lebih banyak tentang sistem operasi dan skema manajemen memorinya daripada C++ itu sendiri. Lagi pula, hal paling primitif yang terjadi ketika Anda mengalokasikan memori penyimpanan bebas (dinamis) adalah bahwa proses tersebut (melalui fungsi perpustakaan standar) memanggil rutinitas OS tertentu untuk mengalokasikan jumlah memori yang diminta dan mengembalikan alamat ke memori yang dialokasikan.

person zxcdw    schedule 22.06.2012

Bug lebih mungkin terjadi jika Anda hanya membuat satu jenis objek. Tapi itu selalu mungkin.

person Jerome    schedule 22.06.2012

Ya itu bisa terjadi. Untuk mencegahnya, saat Anda menghapus suatu objek, telusuri daftarnya dan setel penunjuk apa pun ke objek yang dihapus agar menunjuk ke NULL.

person Daniel    schedule 22.06.2012