2014-07-24 23 views
5

C'de bir proje geliştiriyorum ve ayrılan belleği boşaltmamalı ve ayrıca tüm açık dosyaları çıkmadan önce kapatmalıyım.Küresel değişkenler kullanmadan atexit veya benzer bir şekilde belleği boşaltmanın bir yolu var mı?

Tüm bu işleri yapacak ve atexit numaralı telefondan arayabileceğiniz bir çok clean işlevini uygulamaya karar verdim çünkü birçok olası çıkış senaryosu var.

Sorun, atexit'un işlevlerin parametrelerle ayarlanmasına izin vermemesidir, bu nedenle işlemin sonunda serbest bırakılması gereken işaretçileri clean gönderemiyorum.

Bu yüzden, global değişkenler olarak serbest bırakılması gereken her işaretçi ve programda açık kalabilecek her dosya olarak bildirmem gerekiyor mu? (Bunu zaten yaptım ama iyi görünmüyor) veya parametre göndermeye izin veren atexit'a benzer bir işlev var mı? ya da daha çok, eksik olduğum başka bir yol var mı?

#include <stdio.h> 
#include <stdlib.h> 

void atexit_clean(void *data); 

static void clean(void) 
{ 
    atexit_clean(NULL); 
} 

void atexit_clean(void *data) 
{ 
    static void *x; 

    if (data) { 
     x = data; 
     atexit(clean); 
    } else { 
     free(x); 
    } 
} 

int main(void) 
{ 
    int *a = malloc(sizeof(int)); 

    atexit_clean(a); 
    return 0; 
} 

tek bir genel değişken kullanan diğer bir yöntem: bir işlev içinde statik işaretleyicinin kullanılması

+1

Sadece bellek havuzuna işaret eden bir değişkene ihtiyacınız var. Bu kabul edilebilir görünüyor. – this

+2

Modern bir tüketici işletim sistemindeyseniz, çıktığınızda tüm kaynaklar serbest bırakılır. Yani, tüm ayrılmış dosyalar boşaltılacak, tüm açık dosyalar kapatılacaktır, vb. –

+1

Ayrıca, örn. Tüm süreç çalışma zamanı sırasında açık olması gereken dosyalar, sonra muhtemelen birden fazla yerde erişebilirsiniz, ve bu zaten bir global değişken veya en azından bir çeviri biriminde global olduğu anlamına gelir ve daha sonra yalnızca bir kapatma işlevine sahip olabilirsiniz. global 'clean_all' işlevinden çağrılan dosya. Tahsis ettiğin bellekle aynı. –

cevap

4

işaretçiler arasında bir dizi veya bağlı bir listedeki serbest tüm nesneleri depolamak için, bu örnek realloc kullanır (atexit() herhangi bir parametre iletmek için bir yolu yoktur

#include <stdio.h> 
#include <stdlib.h> 

static void **vclean; 
static size_t nclean; 

void atexit_add(void *data) 
{ 
    vclean = realloc(vclean, sizeof(void *) * (nclean + 1)); 
    vclean[nclean++] = data; 
} 

void clean(void) 
{ 
    size_t i; 

    for (i = 0; i < nclean; i++) { 
     free(vclean[i]); 
    } 
    free(vclean); 
} 

int main(void) 
{ 
    int *a, *b, *c; 
    double *d; 
    int e = 1; 

    atexit(clean); 
    a = &e; 
    b = malloc(sizeof(int)); 
    atexit_add(b); 
    c = malloc(sizeof(int)); 
    atexit_add(c); 
    d = malloc(sizeof(double)); 
    atexit_add(d); 
    return 0; 
} 
+0

'atexit (clean_all);' 'main()' işlevinin başlangıcına hareket etmelisiniz. Gerçekçi bir örnek için “atexit_add()” çağrıları arasında programı sonlandıran işlemler olabilir. – kay

+0

@Kay, temiz bir şekilde bırakmak mı yoksa iptal etmek mi istediğinize bağlı olarak değişir, ancak genelde haklısınız. –

+0

'atexit_add()' 'realloc()' hatasını kontrol etmeli ve arayan kişiye bir hata göstergesi dönmelidir. –

3

global değişkenleri kullanarak takılıp böylece: kısalık için (m/yeniden) alloc) kontrol etmez. Programınız normal olarak exit() aracılığıyla ya da main() numaralı telefondan döndüğünde, otomatik olarak tüm açık akışları ve (çoğu işletim sistemi altında) boş atanan belleği temizler ve kapatacaktır. Ancak, program sona ermeden önce kaynaklarınızı açık bir şekilde temizlemek iyi bir uygulamadır çünkü genellikle daha yapılandırılmış bir programa yol açar. Bazen programınızı yazmanın en temiz yolu, programından çıkıp temizlemeyi uygulamaya bırakmaktır.

Ancak her zaman fclose() dönüş değerini kontrol etmeniz gerektiği konusunda uyarılmalıdır. Yapmadığınızda ne olabileceğine dair bir anektod için "What are the reasons to check for error on close()?" konusuna bakın.

+1

Sadece C standardının * gerektirmediğini * uygulamaların ücretsiz ayrılmış bellek olduğunu unutmayın. Gerçekten de, TI-89 serisi için ortak bir problem, çıkıştan önce temizlenmeyen C programlarıdır ve işletim sistemi * temizlemez *, böylece sızan bir programın tekrarlanan yürütmeleri, hesap makinesinde RAM'i tüketir. –

İlgili konular