Saya ingin tahu apakah mungkin mendeteksi delete
kesalahan yang dikomentari di bawah ini pada waktu kompilasi? Terutama, saya ingin mendengar tentang kompiler g ++.
ClassTypeA *abc_ptr = new ClassTypeA[100];
abc_ptr[10].data_ = 1;
delete abc_ptr; // error, should be delete []
c++
compiler
error-detection
SebGR
sumber
sumber
std::unique_ptr<ClassTypeA[]>
dan kemudian Anda tidak perlu melakukannya.Jawaban:
Secara umum, kompiler tidak dapat mendeteksi kesalahan seperti itu. Contoh: Misalkan konstruktor untuk beberapa kelas mengalokasikan beberapa anggota data menggunakan
new TypeName[]
, tetapi destruktor salah menggunakandelete
sebagai gantinyadelete[]
. Jika konstruktor dan destruktor didefinisikan dalam unit kompilasi terpisah, bagaimana kompiler mengetahui ketika mengkompilasi file yang mendefinisikan destruktor bahwa penggunaannya tidak konsisten dengan yang ada di file yang dikompilasi secara terpisah yang mendefinisikan konstruktor?Berkenaan dengan kompiler GNU, itu tidak. Seperti disebutkan di atas, tidak dapat melakukannya dalam kasus umum. Kompiler tidak harus mendeteksi kesalahan baru / hapus yang tidak cocok karena ini adalah perilaku yang tidak terdefinisi. UB adalah kartu "keluar dari penjara" dari vendor kompiler.
Alat seperti valgrind dapat dan memang mendeteksi ketidakcocokan baru / hapus ini, tetapi melakukannya saat runtime. Mungkin ada alat analisis statis yang melihat semua file sumber yang pada akhirnya akan dikompilasi untuk membentuk executable, tapi saya tidak menemukan alat analisis statis yang mendeteksi kesalahan semacam ini.
sumber
Anda dapat menggunakan kelas RAII yang sesuai untuk
delete
. Ini adalah satu-satunya cara aman untuk melakukannya, dan kesalahan ini hanya salah satu dari sangat, sangat banyak yang Anda temui menyebutdelete
diri Anda.Selalu gunakan kelas untuk mengelola sumber daya seumur hidup yang dinamis, dan sistem tipe akan menegakkan penghancuran sumber daya yang benar.
Sunting: "Bagaimana jika Anda mengaudit kode dan tidak dapat mengubahnya?" Anda kacau.
sumber
Kesalahan khusus ini - ya. Ini jenis kesalahan umum: sayangnya, tidak ada! Itu akan melibatkan memprediksi aliran eksekusi tanpa benar-benar mengeksekusinya, dan itu tidak mungkin untuk program sewenang-wenang. (Itu sebabnya kebanyakan kompiler bahkan tidak mencoba mendeteksi kasus sederhana seperti contoh Anda.)
Karena itu jawaban DeadMG adalah yang tepat: jangan mencoba untuk memperbaikinya dengan memperhatikan - perhatian manusia bisa keliru. Gunakan sarana yang disediakan bahasa dan biarkan komputer memperhatikan.
sumber
ClassTypeA*
sehingga Anda dapat menyisipkan garis antara yang baru dan yang menghapusif ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;
Tidak ada dalam sistem tipe statis yang menunjukkan apakahabc_ptr
menunjuk ke array atau objek dinamis atau bagian jalan ke objek atau array lain.abc_ptr
, jika tidak, bagaimana bisa deallocate jumlah memori yang tepat? Jadi runtime tahu berapa banyak objek yang harus di-deallocated.Kasus sepele yang Anda tunjukkan dapat dideteksi pada waktu kompilasi, karena instantiasi dan penghancuran objek berada dalam cakupan yang sama. Secara umum, penghapusan tidak ada dalam cakupan yang sama, atau bahkan file sumber yang sama, seperti instantiasi. Dan tipe C ++ pointer tidak membawa informasi tentang apakah referensi objek tunggal dari jenis atau array, apalagi skema alokasi. Jadi tidak mungkin untuk mendiagnosis ini pada waktu kompilasi secara umum.
Mengapa tidak mendiagnosis kasus khusus yang mungkin terjadi?
Di C ++ sudah ada alat untuk menangani kebocoran sumber daya dinamis yang terkait dengan cakupan, yaitu smart pointer dan array level yang lebih tinggi (
std::vector
).Bahkan jika Anda menggunakan
delete
rasa yang benar , kode Anda masih tidak terkecuali aman. Jika kode antaranew[]
dandelete[]
diakhiri dengan keluar dinamis, penghapusan tidak pernah dijalankan.Sejauh deteksi run-time berjalan,
Valgrind
alat melakukan pekerjaan yang baik untuk mendeteksi ini pada saat run-time. Menonton:Tentu saja, Valgrind tidak berjalan pada semua platform, dan tidak selalu praktis atau mungkin untuk mereproduksi semua situasi run-time di bawah alat ini.
sumber
Beberapa contoh deteksi yang sepele pada waktu kompilasi / analisis-statis:
Pada host RHEL7 dengan
cppcheck 1.77 and 1.49
http://cppcheck.sourceforge.net/
Dengan
clang++ 3.7.1
di RHEL7The Clang Static Analyzer juga dapat mendeteksi kapan
std::unique_ptr
tidak lulus<char[]>
https://clang-analyzer.llvm.org/
Perbarui di bawah ini dengan tautan ke pekerjaan yang menambahkan ini ke dentang, tes dan satu bug yang saya temukan.
Ini ditambahkan ke dentang dengan reviews.llvm.org/D4661 - "Deteksi ketidakcocokan penggunaan 'baru' dan 'hapus'" .
Tes dalam tes / Analisis / MismatchedDeallocator-checker-test.mm
Saya menemukan bug terbuka ini - bugs.llvm.org/show_bug.cgi?id=24819
sumber