Ücretsiz (ptr) nerede ptr BOŞ bellek bozuk mu?


112

Teorik olarak şunu söyleyebilirim

free(ptr);
free(ptr); 

Zaten serbest bırakılan belleği boşalttığımız için bir bellek bozulmasıdır.

Ama ya eğer

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

İşletim sistemi tanımlanmamış bir şekilde davranacağından, neler olduğuna dair bunun için gerçek bir teorik analiz elde edemiyorum. Ne yaparsam yapayım, bu bellek bozulması mı, değil mi?

NULL işaretçisi serbest bırakmak geçerli midir?


1
C serbest standardından emin değilim, ancak C ++ 'da silme (NULL) mükemmel bir şekilde geçerlidir, bu yüzden sanırım ücretsiz (NULL) da olmalıdır.
Priyank Bolia

14
@Pryank: delete NULLC ++ 'da geçerli değil. delete somut türdeki boş işaretçi değerlerine uygulanabilir, ancak uygulanamaz NULL. delete (int*) NULLyasal, ancak değil delete NULL.
AnT

yani bir işaretçi NULL free'yi gösteriyorsa hiçbir şey yapmaz. bu demek oluyor !!!!!! kodlamamızda her seferinde bir hafızayı boşaltmak istersek, basitçe bir boş (ptr) yerine ptr = NULL olabilir mi?
Vijay

3
Hayır ptr. Hafızayı gösteriyorsa ve onu çağırmazsanız free, hafıza sızdırır. Bunu NULLsadece hafıza üzerindeki kontrolünüzü kaybedecek şekilde ayarlamak ve sızıntılara neden olur. Eğer ptr olurNULL , çağrı freeno-operasyonlar olduğunu.
GManNickG

1
@benjamin: Ha? Ne değiştirebilirsiniz sonucuna kıldık free(ptr)ile ptr = NULL. Kimse böyle bir şey söylemedi.
AnT

Yanıtlar:


225

7.20.3.2 freeİşlev

özet

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

Açıklama

freeFonksiyonu ile gösterilen boşluk neden ptrolup, ayrıca tahsis için uygun hale getirilir ayırmanın. Eğer ptrbir boş gösterici, herhangi bir işlem gerçekleşir.

ISO-IEC 9899'a bakın .

Bununla birlikte, vahşi doğada farklı kod tabanlarına baktığınızda, insanların bazen şunları yaptığını fark edeceksiniz:

if (ptr)
  free(ptr);

Bunun nedeni, bazı C çalışma zamanlarının (PalmOS'ta durum olduğunu kesinlikle hatırlıyorum) bir NULLişaretçiyi serbest bırakırken çökmesidir .

Ancak günümüzde, free(NULL)standardın talimatına göre bir hayır olduğunu varsaymanın güvenli olduğuna inanıyorum .


29
Hayır, ptr = NULL hiçbir şekilde ücretsiz (ptr) yerine
geçmez

7
HAYIR, boş olan free(ptr)yerin ptryan etkisi olmadığı anlamına gelir . Ancak her durumda, kullanılarak tahsis edilen her bellek malloc()veya calloc()daha sonra kullanılarak serbest bırakılmalıdırfree()
Gregory Pakosz

4
ptr = NULL, yanlışlıkla bedava (ptr) çağırsanız bile programınızın segfault olmamasını sağlar.
Prasoon Saurav

2
Lütfen, C standardının işlemsiz olduğunu söylese de, bunun her C kütüphanesinin bunu bu şekilde ele aldığı anlamına gelmediğini unutmayın. Ücretsiz (NULL) çökmeler gördüm, bu yüzden ilk etapta ücretsiz olarak aramaktan kaçınmak en iyisidir.
Derick

6
@WereWolfBoy free(NULL), NULLaramadan önce işaretçiyi test ederek kaçınmak demekfree()
Gregory Pakosz

22

C kütüphanesinin tüm standartlara uyumlu sürümleri, ücretsiz (NULL) işlemsiz olarak davranır.

Bununla birlikte, bir zamanlar ücretsiz (NULL) çökecek bazı ücretsiz sürümleri vardı, bu yüzden bazı savunma programlama tekniklerinin önerildiğini görebilirsiniz:

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

8
-1 [alıntı gerekli]. Arkaik bir söylenti uygulamasına dair bazı teoriler nedeniyle kod stilini değiştirmek kötü bir fikirdir.
Tomas

41
@Tomas - Tarz değiştirmeyi asla önermedim, sadece bu öneriyi neden bazı stillerde görebileceğinizi açıkladım.
R Samuel Klatchko

5
@Tomas 3BSD ( winehq.org/pipermail/wine-patches/2006-October/031544.html ) ve iki kişi için PalmOS (her ikisi için 2. el).
Douglas Leeder

7
@Tomas: Sorun, Sürüm 7 Unix gibi şeylerdeydi. Öğrenirken, ücretsiz (xyz), burada xyz == NULL, öğrendiğim makinede anlık felaket için bir reçeteydi (ICL Perq, bazı Sistem III ekstralarıyla Sürüm 7 Unix'e dayanan PNX'i çalıştırıyordu). Ama uzun zamandır bu şekilde kodlamadım.
Jonathan Leffler

2
Netware, NULL serbest bırakıldığında da çöküyor ... (sadece üzerinde bir çökme
hatası ayıkladı


12

Düştüğü yerde PalmOS üzerinde çalıştığımı hatırlıyorum free(NULL).


4
İlginç - bu, çöken ikinci bir platform (3BSD'den sonra) yapar.
Douglas Leeder

2
Doğru hatırlıyorsam, Palm'da C Standart Kitaplığı yoktu. Bunun yerine, standart kitaplık çağrılarını Palm OS SDK ile eşleştiren çoğunlukla desteklenmeyen bir başlık dosyası vardı. Pek çok şey beklenmedik şekilde hareket etti. Kilitlenme NULL, standart kitaplığa kıyasla Palm araç kutusunun en büyük çalışma farklılıklarından biriydi.
Steven Fisher

8
free(ptr);
ptr=NULL;
free(ptr);/*This is perfectly safe */

NULL işaretçisini güvenle silebilirsiniz. Bu durumda hiçbir işlem yapılmayacaktır.Başka bir deyişle free () bir NULL göstericide hiçbir şey yapmaz.


8

Önerilen kullanım:

free(ptr);
ptr = NULL;

Görmek:

man free

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

İmleci tekrar çağırdıktan NULLsonra olarak ayarladığınızda hiçbir işlem gerçekleştirilmez.free()free()


3
Bu ayrıca bir hata ayıklayıcı ile segfault'ları tespit etmeye yardımcı olur. P-> do () 'daki segfault'un p = 0 ile serbest gösterici kullanan biri olduğu açıktır. Hata ayıklayıcıda p = 0xbfade12 gördüğünüzde daha az belirgin :)
neuro

6

free(NULL)mükemmel C yasal yanı sıra olduğunu delete (void *)0ve delete[] (void *)0C ++ olan yasal.

BTW, belleği iki kez boşaltmak genellikle bir tür çalışma zamanı hatasına neden olur, bu nedenle hiçbir şeyi bozmaz.


2
delete 0C ++ 'da yasal değildir. deleteaçıkça işaretçi tipi bir ifade gerektirir. deleteYazılı bir boş işaretçi değerine uygulanması yasaldır , ancak buna uygulanmaz 0(ve uygulanmaz NULL).
AnT

1
İkisini de silemezsiniz void*: P Hangi yıkıcı (lar) çalıştırmalı?
GManNickG

1
@GMan: Sen edebilirsiniz silmek void *sürece bir boşlukla gösterici olarak.
AnT

Tamam, yeterince adil. Sadece özellikle null ile uğraştığımızı unuttum.
GManNickG

genellikle hiçbir şeyi bozmaz, ancak garanti edilmez. ASLR bunu pek olası değil, ama yine de imkansız değil: buf1=malloc(X); free(buf1);buf2=malloc(X);free(buf1); - burada şanssızsanız, buf2 buf1 ile tam olarak aynı adresi aldı ve buf1'i yanlışlıkla iki kez serbest bıraktınız, bu yüzden 2.'de buf1'den arınmadan buf2'yi sessizce serbest bıraktınız. herhangi bir (ani) hata / çökme / her neyse. (ancak bir dahaki sefere buf2'yi kullanmaya çalıştığınızda muhtemelen çökme yaşayacaksınız - ve ASLR üzerinde koşuyorsanız bu senaryo çok düşük bir ihtimaldir)
hanshenrik

3

free(ptr)C'de tasarruf, eğer öyleyse ptr, NULLçoğu insanın bilmediği şey bunun NULL0'a eşit olması gerekmediğidir. Güzel bir eski okul örneğim var: C64'te, adres 0'da bir IO-Portu var. Bu bağlantı noktasına erişen bir program yazdıysanız, değeri 0 olan bir göstericiye ihtiyacınız olacaktır. Karşılık gelen C kütüphanesinin 0 ve NULLsonra arasında ayrım yapması gerekir .

Saygılarımla.


İlginç gerçek, beni şaşırttı. NULL işaretçi soruları / cevapları etrafında bir gezintiye çıkmaya mecbur hissettirdi.
eklem bacaklılar

0

bellek bozulması değil, ancak davranış uygulamaya bağlıdır. Standart olarak, yasal bir kod olmalıdır.


-3

ptr bir bellek konumunu işaret ediyor, 0x100 diyelim.

Serbest bıraktığınızda (ptr), temelde 0x100'ün bellek yöneticisi tarafından diğer faaliyetler veya işlemler için kullanılmasına izin verirsiniz ve basit bir deyişle, kaynakların serbest bırakılmasıdır.

Ptr = NULL yaptığınızda, ptr'yi yeni konuma işaret ediyorsunuz (NULL'un ne olduğu konusunda endişelenmeyelim). Bunu yaptığınızda 0x100 bellek verilerinin izini kaybettiniz. Bellek sızıntısı budur.

Bu nedenle, geçerli bir ptr üzerinde ptr = NULL kullanılması tavsiye edilmez.

Bunun yerine şunları kullanarak güvenli bir kontrol yapabilirsiniz:

eğer (ptr! = NULL) {ücretsiz (ptr);}

Ptr'nin zaten NULL'u işaret ettiği serbest (ptr) olduğunuzda, hiçbir işlem yapmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.