$1.99 Domains* at GoDaddy.com

C Programlama Dinamik Bellek Yönetimi

c_programlama-118Dizileri etkin bir biçimde kullanmayı öğrendiÄŸinizi ya da öğreneceÄŸinizi umuyorum. Ancak dizilerle ilgili iÅŸlememiz gereken son bir konu var: Dinamik Bellek Yönetimi…

Şimdiye kadar yazdığımız programlarda kaç eleman olacağı önceden belliydi. Yani sınıf listesiyle ilgili bir program yazacaksak, sınıfın kaç kişi olduğunu biliyormuşuz gibi davranıyorduk. Programın en başında kaç elemanlık alana ihtiyacımız varsa, o kadar yer ayırıyorduk. Ama bu gerçek dünyada karşımıza çıkacak problemler için yeterli bir yaklaşım değildir. Örneğin bir sınıfta 100 öğrenci varken, diğer bir sınıfta 50 öğrenci olabilir ve siz her ortamda çalışsın diye 200 kişilik bir üst sınır koyamazsınız. Bu, hem hafızanın verimsiz kullanılmasına yol açar; hem de karma eğitimlerin yapıldığı bazı fakültelerde sayı yetmeyebilir. Statik bir şekilde dizi tanımlayarak bu sorunların üstesinden gelemezsiniz. Çözüm dinamik bellek yönetimindedir.

Dinamik bellek yönetiminde, dizilerin boyutları önceden belirlenmez. Program akışında dizi boyutunu ayarlarız ve gereken bellek miktarı, program çalışırken tahsis edilir. Dinamik bellek tahsisi için calloc(  ) ve malloc(  ) olmak üzere iki önemli fonksiyonumuz vardır. Bellekte yer ayrılmasını bu fonksiyonlarla sağlarız. Her iki fonksiyon da stdlib kütüphanesinde bulunur. Bu yüzden fonksiyonlardan herhangi birini kullanacağınız zaman, programın başına #include<stdlib.h> yazılması gerekir.

calloc(  ) fonksiyonu aşağıdaki gibi kullanılır:

isaretci_adi = calloc( eleman_sayisi, her_elemanin_boyutu );

calloc(  ) fonksiyonu eleman sayısını, eleman boyutuyla çarparak hafızada gereken bellek alanını ayırır. Dinamik oluşturduğunuz dizi içersindeki her elemana, otomatik olarak ilk değer 0 atanır.

malloc(  ) fonksiyonu, calloc(  ) gibi dinamik bellek ayrımı için kullanılır. calloc(  ) fonksiyonundan farklı olarak ilk değer ataması yapmaz. Kullanımıysa aşağıdaki gibidir:

isaretci_adi = malloc( eleman_sayisi * her_elemanin_boyutu );

Bu kadar konuşmadan sonra işi pratiğe dökelim ve dinamik bellekle ilgili ilk programımızı yazalım:

#include<stdio.h>
#include<stdlib.h>
int main( void )
{
	// Dinamik bir dizi yaratmak icin
	// pointer kullaniriz.
	int *dizi;

	// Dizimizin kac elemanli olacagini
	// eleman_sayisi isimli degiskende
	// tutuyoruz.
	int eleman_sayisi;
	int i;

	// Kullanicidan eleman sayisini girmesini
	// istiyoruz.
	printf( "Eleman sayısını giriniz> ");
	scanf( "%d", &eleman_sayisi );

	// calloc( ) fonksiyonuyla dinamik olarak
	// dizimizi istedigimiz boyutta yaratiyoruz.
	dizi = calloc( eleman_sayisi, sizeof( int ) );

	// Ornek olmasi acisindan dizinin elemanlarini
	// ekrana yazdiriliyor. Dizilerde yapabildiginiz
	// her seyi hicbir fark olmaksizin yapabilirsiniz.
	for( i = 0; i < eleman_sayisi; i++ )
		printf( "%d\n", dizi[i] );

	// Dinamik olan diziyi kullandiktan ve isinizi
	// tamamladiktan sonra free fonksiyonunu kullanip
	// hafizadan temizlemelisiniz.
	free( dizi );

	return 0;
}

Yazdığınız programların bir süre sonra bilgisayar belleÄŸini korkunç bir ÅŸekilde iÅŸgal etmesini istemiyorsanız, free(  ) fonksiyonunu kullanmanız gerekmektedir. GeliÅŸmiÅŸ programlama dillerinde ( örneÄŸin, Java, C#, vb… ) kullanılmayan nesnelerin temizlenmesi otomatik olarak çöp toplayıcılarla ( Garbage Collector ) yapılmaktadır. Ne yazık ki C programlama dili için bir çöp toplayıcı yoktur ve iyi programcıyla, kötü programcı burada kendisini belli eder.

Programınızı bir kereliğine çalıştırıyorsanız ya da yazdığınız program çok ufaksa, boş yere tüketilen bellek miktarını farketmeyebilirsiniz. Ancak büyük boyutta ve kapsamlı bir program söz konusuysa, efektif bellek yönetiminin ne kadar önemli olduğunu daha iyi anlarsınız. Gereksiz tüketilen bellekten kaçınmak gerekmektedir. Bunun için fazla bir şey yapmanız gerekmez; calloc(  ) fonksiyonuyla tahsis ettiğiniz alanı, işiniz bittikten sonra free(  ) fonksiyonuyla boşaltmanız yeterlidir. Konu önemli olduğu için tekrar ediyorum; artık kullanmadığınız bir dinamik dizi söz konusuysa onu free(  ) fonksiyonuyla kaldırılabilir hâle getirmelisiniz!

Az evvel calloc(  ) ile yazdığımız programın aynısını şimdi de malloc(  ) fonksiyonunu kullanarak yazalım:

#include<stdio.h>
#include<stdlib.h>
int main( void )
{
	// Dinamik bir dizi yaratmak icin
	// pointer kullaniriz.
	int *dizi;
	// Dizimizin kac elemanli olacagini
	// eleman_sayisi isimli degiskende
	// tutuyoruz.
	int eleman_sayisi;
	int i;

	printf( "Eleman sayısını giriniz> ");
	scanf( "%d", &eleman_sayisi );

	// malloc( ) fonksiyonuyla dinamik olarak
	// dizimizi istedigimiz boyutta yaratiyoruz.
	dizi = malloc( eleman_sayisi * sizeof( int ) );

	for( i = 0; i < eleman_sayisi; i++ )
		printf( "%d\n", dizi[i] );

	// Dinamik olan diziyi kullandiktan ve isinizi
	// tamamladiktan sonra free fonksiyonunu kullanip
	// hafizadan temizlemelisiniz.
	free( dizi );

	return 0;
}

Hafıza alanı ayırırken bazen bir problem çıkabilir. Örneğin bellekte yeterli alan olmayabilir ya da benzeri bir sıkıntı olmuştur. Bu tarz problemlerin sık olacağını düşünmeyin. Ancak hafızanın gerçekten ayrılıp ayrılmadığını kontrol edip, işinizi garantiye almak isterseniz, aşağıdaki yöntemi kullanabilirsiniz:

	dizi = calloc( eleman_sayisi, sizeof( int ) );
	// Eger hafiza dolmussa dizi pointer'i NULL'a
	// esit olacak ve asagidaki hata mesaji cikacaktir.
	if( dizi == NULL )
		printf( "Yetersiz bellek!\n" );

Dinamik hafıza kullanarak dizi yaratmayı gördük. Ancak bu diziler tek boyutlu dizilerdi. Daha önce pointer iÅŸaret eden pointer’ları görmüştük. Åžimdi onları kullanarak dinamik çok boyutlu dizi oluÅŸturacağız:

#include<stdio.h>
#include<stdlib.h>
int main( void )
{
	int **matris;
	int satir_sayisi, sutun_sayisi;
	int i, j;
	printf( "Satır sayısı giriniz> " );
	scanf( "%d", &satir_sayisi );
	printf( "Sütun sayısı giriniz> " );
	scanf( "%d", &sutun_sayisi );

	// Once satir sayisina gore hafizada yer ayiriyoruz.
	// Eger gerekli miktar yoksa, uyari veriliyor.
	matris = (int **)malloc( satir_sayisi * sizeof(int) );
	if( matris == NULL )
		printf( "Yetersiz bellek!" );

	// Daha sonra her satirda, sutun sayisi kadar hucrenin
	// ayrilmasini sagliyoruz.
	for( i = 0; i < satir_sayisi; i++ ) {
		matris[i] = malloc( sutun_sayisi * sizeof(int) );
		if( matris[i] == NULL )
			printf( "Yetersiz bellek!" );
	}

	// Ornek olmasi acisindan matris degerleri
	// gosteriliyor. Dizilerde yaptiginiz butun
	// islemleri burada da yapabilirsiniz.
	for( i = 0; i < satir_sayisi; i++ ) {
		for( j = 0; j < sutun_sayisi; j++ )
			printf( "%d ", matris[i][j] );
		printf( "\n" );
	}

	// Bu noktada matris ile isimiz bittiginden
	// hafizayi bosaltmamiz gerekiyor. Oncelikle
	// satirlari bosaltiyoruz.
	for( i = 0; i < satir_sayisi; i++ ) {
		free( matris[i] );
	}
	// Satirlar bosaldiktan sonra, matrisin
	// bos oldugunu isaretliyoruz.
	free( matris );

	return 0;
}

Yukardaki örnek karmaşık gelebilir; tek seferde çözemeyebilirsiniz. Ancak bir iki kez üzerinden geçerseniz, temel yapının aklınıza yatacağını düşünüyorum. Kodun koyu yazılmış yerlerini öğrendiğiniz takdirde, sorun kalmayacaktır.

Kategoriler: Visual Basic, Yazılım

Tags: , , ,

Yorumlar

Yorum Yok

Yorumunuzu Ekleyin

Yorum eklemek için giris yapmalısınız.