Apakah free (ptr) di mana ptr adalah NULL memori korup?

112

Secara teoritis saya bisa mengatakan itu

free(ptr);
free(ptr); 

adalah kerusakan memori karena kita membebaskan memori yang telah dibebaskan.

Tapi bagaimana jika

free(ptr);
ptr=NULL;
free(ptr); 

Karena OS akan berperilaku dengan cara yang tidak ditentukan, saya tidak bisa mendapatkan analisis teoritis aktual untuk ini tentang apa yang terjadi. Apapun yang saya lakukan, apakah ingatan ini rusak atau tidak?

Apakah membebaskan pointer NULL valid?

Vijay
sumber
1
tidak yakin tentang standar C gratis, tetapi dalam C ++ delete (NULL) benar-benar valid, jadi saya kira gratis (NULL) juga harus.
Priyank Bolia
14
@Pryank: delete NULLtidak valid di C ++. delete dapat diterapkan ke nilai null-pointer dari tipe beton, tetapi tidak untuk NULL. delete (int*) NULLlegal, tapi tidak delete NULL.
AnT
jadi itu berarti jika pointer yang menunjuk ke NULL gratis tidak melakukan apa-apa. apakah itu berarti !!!!!! setiap kali di koding kita jika ingin mengosongkan memory bisa langsung mengganti free (ptr) dengan ptr = NULL?
Vijay
3
Tidak. Jika ptrmenunjuk ke memori, dan Anda tidak memanggilnya free, maka memori tersebut akan bocor. Menyetelnya menjadi NULLhanya kehilangan pegangan pada memori, dan kebocoran. Jika ptr kebetulanNULL , panggilan freeadalah tidak ada operasi.
GManNickG
1
@benjamin: Hah? Apa yang membuat Anda menyimpulkan bahwa Anda bisa mengganti free(ptr)dengan ptr = NULL. Tidak ada yang mengatakan hal seperti itu.
AnT

Jawaban:

224

7.20.3.2 freeFungsi

Ringkasan

#include <stdlib.h> 
void free(void *ptr); 

Deskripsi

The freeFungsi menyebabkan ruang ditunjuk oleh ptruntuk deallocated, yang, dibuat tersedia untuk alokasi lebih lanjut. Jika ptrpointer nol, tidak ada tindakan yang terjadi.

Lihat ISO-IEC 9899 .

Meskipun demikian, saat melihat basis kode yang berbeda di alam liar, Anda terkadang akan melihat orang melakukan:

if (ptr)
  free(ptr);

Ini karena beberapa runtime C (saya pasti ingat itu yang terjadi di PalmOS) akan macet saat membebaskan NULLpointer.

Tapi saat ini, saya yakin aman untuk berasumsi free(NULL)adalah nop sesuai instruksi standar.

Gregory Pakosz
sumber
29
Tidak, ptr = NULL bukanlah cara pengganti gratis (ptr), keduanya sama sekali berbeda
Prasoon Saurav
7
TIDAK, artinya di free(ptr)mana ptrnol tidak memiliki efek samping. Tapi bagaimanapun, setiap memori yang dialokasikan menggunakan malloc()atau calloc()harus dilepaskan setelahnya menggunakanfree()
Gregory Pakosz
4
ptr = NULL memastikan bahwa meskipun Anda secara tidak sengaja memanggil free (ptr), program Anda tidak akan segfault.
Prasoon Saurav
2
Harap dicatat bahwa meskipun standar C mengatakan itu adalah no-op, itu tidak berarti bahwa setiap C-library menanganinya seperti itu. Saya telah melihat crash gratis (NULL), jadi yang terbaik adalah menghindari menelepon gratis di tempat pertama.
Derick
6
@WereWolfBoy maksudnya hindari free(NULL)dengan menguji pointer terhadap NULLsebelum meneleponfree()
Gregory Pakosz
22

Semua versi library C yang memenuhi standar memperlakukan free (NULL) sebagai no-op.

Yang mengatakan, pada suatu waktu ada beberapa versi gratis yang akan mogok pada gratis (NULL) itulah sebabnya Anda mungkin melihat beberapa teknik pemrograman defensif merekomendasikan:

if (ptr != NULL)
    free(ptr);
R Samuel Klatchko
sumber
8
-1 [butuh rujukan]. Mengubah gaya kode karena beberapa teori implementasi desas-desus kuno adalah ide yang buruk.
Tomas
41
@Tomas - Saya tidak pernah merekomendasikan untuk mengubah gaya, saya hanya menjelaskan mengapa Anda mungkin masih melihat rekomendasi ini dalam beberapa gaya.
R Samuel Klatchko
5
@Tomas 3BSD ( winehq.org/pipermail/wine-patches/2006-October/031544.html ) dan PalmOS untuk dua (tangan kedua untuk keduanya).
Douglas Leeder
7
@ Tomas: masalahnya ada pada hal-hal seperti Versi 7 Unix. Ketika saya belajar, gratis (xyz) di mana xyz == NULL adalah resep untuk bencana instan di mesin tempat saya belajar (ICL Perq menjalankan PNX, yang didasarkan pada Versi 7 Unix dengan beberapa tambahan Sistem III). Tapi saya sudah lama tidak membuat kode seperti itu.
Jonathan Leffler
2
Netware juga crash saat membebaskan NULL ... (baru saja men-debug crash di atasnya ...)
Calmarius
13

Jika ptr adalah NULL, tidak ada operasi yang dilakukan.

kata dokumentasinya.

Michael Krelin - peretas
sumber
maksudmu bebas tidak akan melakukan apa-apa?
Vijay
2
benjamin, itulah artinya. Apa yang Anda harapkan untuk dilakukan jika mengetahui nullness argumen?
Michael Krelin - hacker
12

Saya ingat bekerja di PalmOS yang free(NULL)mengalami crash.

jlru
sumber
4
Menarik - yang membuat platform kedua (setelah 3BSD) mengalami crash.
Douglas Leeder
2
Jika saya ingat dengan benar, di Palm C Standard Library tidak ada. Sebaliknya, ada file header yang sebagian besar tidak didukung yang memetakan panggilan perpustakaan standar ke Palm OS SDK. Banyak hal yang terjadi secara tidak terduga. Menabrak NULLadalah salah satu perbedaan besar dari toolbox Palm dibandingkan dengan perpustakaan standar.
Steven Fisher
8
free(ptr);
ptr=NULL;
free(ptr);/*This is perfectly safe */

Anda dapat dengan aman menghapus penunjuk NULL. Tidak ada operasi yang akan dilakukan dalam kasus itu.Dengan kata lain free () tidak melakukan apa pun pada penunjuk NULL.

Prasoon Saurav
sumber
8

Penggunaan yang direkomendasikan:

free(ptr);
ptr = NULL;

Lihat:

man free

     The free() function deallocates the memory allocation pointed to by ptr.
     If ptr is a NULL pointer, no operation is performed.

Saat Anda mengatur penunjuk ke NULLsetelah free()Anda dapat memanggilnya free()lagi dan tidak ada operasi yang akan dilakukan.

StefanB
sumber
3
Itu juga membantu untuk menemukan segfault dengan debugger. Terbukti bahwa segfault di p-> do () dengan p = 0 adalah seseorang yang menggunakan penunjuk bebas. Kurang jelas ketika Anda melihat p = 0xbfade12 di debugger :)
neuro
6

free(NULL)legal di C delete (void *)0dan delete[] (void *)0juga legal di C ++.

BTW, membebaskan memori dua kali biasanya menyebabkan beberapa jenis kesalahan waktu proses, jadi tidak merusak apa pun.

n0rd
sumber
2
delete 0tidak legal di C ++. deletesecara eksplisit membutuhkan ekspresi tipe pointer. Adalah legal untuk menerapkan deleteke nilai penunjuk null yang diketik, tetapi tidak untuk 0(dan tidak untuk NULL).
AnT
1
Anda juga tidak dapat menghapus void*: P Perusak mana yang harus dijalankan?
GManNickG
1
@GMan: Anda dapat menghapus void *selama itu adalah null-pointer.
AnT
OK cukup adil. Saya lupa kami hanya berurusan secara khusus dengan null.
GManNickG
biasanya tidak merusak apa pun, tetapi tidak dijamin. ASLR membuat ini agak tidak mungkin, tetapi tetap bukan tidak mungkin: buf1=malloc(X); free(buf1);buf2=malloc(X);free(buf1); - di sini jika Anda tidak beruntung, buf2 mendapat alamat yang sama persis dengan buf1, dan Anda secara tidak sengaja membebaskan buf1 dua kali, jadi pada tanggal 2 bebas buf1 Anda benar-benar membebaskan buf2 secara diam-diam, tanpa casuing setiap kesalahan (segera) / crash / apapun. (tetapi Anda mungkin masih akan mengalami crash saat Anda mencoba menggunakan buf2 - dan skenario ini sangat tidak mungkin jika Anda menjalankan ASLR)
hanshenrik
3

free(ptr)disimpan di C jika ptrada NULL, namun, apa yang kebanyakan orang tidak tahu adalah bahwa NULLkebutuhannya tidak harus sama dengan 0. Saya punya contoh jadul yang bagus: Di C64, di alamat 0, ada IO-Port. Jika Anda menulis program di C dengan mengakses port ini, Anda memerlukan pointer yang nilainya 0. Library C yang sesuai harus membedakan antara 0 danNULL kemudian.

Salam.

andi8086
sumber
Fakta menarik, mengejutkan saya. Membuat saya merasa terdorong untuk melakukan perjalanan di sekitar pertanyaan / jawaban pointer NULL.
arthropoda
0

bukan kerusakan memori, tetapi perilaku bergantung pada implementasi. Secara standar, itu harus menjadi kode hukum.

Pavel Radzivilovsky
sumber
-3

ptr menunjuk ke beberapa lokasi memori, katakanlah 0x100.

Ketika Anda membebaskan (ptr), pada dasarnya Anda mengizinkan 0x100 digunakan oleh pengelola memori untuk digunakan untuk aktivitas atau proses lain dan dengan kata sederhana itu adalah deallokasi sumber daya.

Ketika Anda melakukan ptr = NULL, Anda membuat titik ptr ke lokasi baru (jangan khawatir tentang apa itu NULL). Melakukan ini, Anda kehilangan jejak data memori 0x100. Inilah yang disebut kebocoran memori.

Jadi, tidak disarankan untuk menggunakan ptr = NULL pada ptr yang valid.

Sebagai gantinya, Anda dapat melakukan pemeriksaan aman dengan menggunakan:

if (ptr! = NULL) {free (ptr);}

Ketika Anda membebaskan (ptr) di mana ptr sudah mengarah ke NULL, itu tidak melakukan operasi, jadi aman untuk melakukannya.

kishanp
sumber