Bellek Ayırma Hatasını Kontrol Etme
Coddy'nin C Journey'sinin Logic & Flow bölümünün bir parçası — ders 34 / 63.
malloc() dinamik bellek ayırma için güçlü bir araç olsa da, anlamanız gereken kritik bir gerçek var: malloc() başarısız olabilir. Sistemde kullanılabilir bellek tükendiğinde, malloc() isteğinizi yerine getiremez ve geçerli bir bellek adresi yerine NULL döndürür.
Bu, her malloc() kullandığınızda, dönen işaretçiyi kullanmaya çalışmadan önce işlemin başarılı olup olmadığını kontrol etmeniz gerektiği anlamına gelir. NULL bir işaretçi kullanmak, programınızın bir segmentasyon hatası (segmentation fault) ile çökmesine neden olacaktır.
int *ptr = (int*)malloc(sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return -1; // Programdan çıkın veya hatayı yönetin
}
// Burada ptr kullanmak güvenlidir
*ptr = 42;Bu NULL kontrolü isteğe bağlı değildir - sağlam C programları yazmak için temeldir. Modern sistemlerde bellek ayırma hataları nadir olsa bile, özellikle kaynak kısıtlı ortamlarda veya büyük miktarlarda bellek istenirken meydana gelebilirler. Profesyonel C kodu, çökmeleri önlemek ve düzgün hata yönetimi sağlamak için her zaman bu kontrolleri içerir.
Görev
KolayDinamik bellek tahsisi için malloc() kullanırken uygun hata yönetimini gösteren bir C programı yazın. Programınız şunları yapmalıdır:
- Kullanıcıdan saklanacak tam sayı adedini temsil eden bir
ntam sayısı okuyun nadet tam sayıdan oluşan bir dizi için belleği dinamik olarak tahsis etmek üzeresizeof()ile birliktemalloc()kullanın- Dönen işaretçinin (pointer)
NULLolup olmadığını test ederek bellek tahsisinin başarılı olup olmadığını kontrol edin - Tahsis başarısız olursa,
Memory allocation failed!yazdırın ve programı sonlandırın - Tahsis başarılı olursa,
Memory allocation successful!yazdırın - Kullanıcıdan
nadet tam sayı değeri okuyun ve bunları tahsis edilen dizide saklayın - Tüm değerlerin toplamını şu formatta hesaplayın ve yazdırın:
Sum: [value] - Tahsis edilen toplam bayt miktarını şu formatta yazdırın:
Bytes allocated: [value]
malloc() kullanmak için <stdlib.h> başlık dosyasını dahil etmeyi unutmayın. Programınız, tahsis edilen belleği kullanmaya çalışmadan önce tahsis hatasını kontrol etme şeklindeki temel uygulamayı göstermelidir.
Örneğin, giriş şu şekildeyse:
4
10 20 30 40Çıktınız şu şekilde olmalıdır:
Memory allocation successful!
Sum: 100
Bytes allocated: 16Bu zorluk, dinamik bellek tahsisi ile çalışırken savunmacı programlamanın (defensive programming) kritik önemini vurgulayarak, programlarınızın olası bellek tahsisi hatalarını beklenmedik şekilde çökmek yerine zarif bir şekilde ele almasını sağlar.
Kopya kağıdı
Tahsis edilen belleği kullanmadan önce her zaman malloc() fonksiyonunun NULL döndürüp döndürmediğini kontrol edin:
int *ptr = (int*)malloc(sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return -1; // Programdan çıkın veya hatayı yönetin
}
// Burada ptr kullanmak güvenlidir
*ptr = 42;Sistemde kullanılabilir bellek bittiğinde malloc() başarısız olabilir. NULL bir işaretçi kullanmak segmentasyon hatasına (segmentation fault) neden olur. Bu NULL kontrolü, sağlam C programları yazmak ve çökmeleri önlemek için gereklidir.
Kendin dene
#include <stdio.h>
#include <stdlib.h>
int main() {
// Tam sayıların sayısını oku
int n;
scanf("%d", &n);
// YAPILACAK: Kodunuzu buraya yazın
// - n tam sayı için bellek ayırmak üzere malloc() kullanın
// - Ayırma işleminin başarılı olup olmadığını kontrol edin
// - Hem başarı hem de hata durumlarını ele alın
// - Tam sayıları okuyun ve saklayın
// - Toplamı ve ayrılan bayt miktarını hesaplayın
return 0;
}Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Logic & Flow bölümündeki tüm dersler
1Pointer Temelleri
Pointer Nedir?Pointer TanımlamaAdres Operatörü (&)Dereference Operatörü (*)NULL Pointer'larÖzet: Pointer Temelleri4Proje: Basit Metin Aracı
Projeye Genel BakışKarakter Sayma2İşaretçiler ve Diziler
İşaretçi Olarak Dizi İsimleriDizi Elemanları - İşaretçilerİşaretçi Aritmetiğiİşaretçilerin KarşılaştırılmasıÖzet: İşaretçi ile Dizi Gezinme5İşaretçiler ve Fonksiyonlar
Değer ile GeçmeFonksiyonlara İşaretçi Göndermeİşaretçiler ile Değişkenleri DeğiştirmeKlasik Bir Örnek: SwapFonksiyonlara Dizi GöndermeÖzet: Fonksiyon İşaretçi Argümanları8Yapılar ve İşaretçiler
Yapılara İşaretçilerOk Operatörü (->)Yapıları Değer ile AktarmaYapı İşaretçilerini AktarmaYapıların Dinamik TahsisiÖzet: Yapıyı Değiştirme - Ptr11Son Tekrar Görevleri
Tekrar: Dinamik String BirleştirmeTekrar: Struct DizisiTekrar: Kelime Frekans Sayacı3Karakter Dizileri ve Stringler
char Dizisi Olarak StringlerNull Sonlandırıcıscanf ile String Girişistrlen() Kullanımıstrcpy() Kullanımıstrcat() Kullanımıstrcmp() KullanımıÖzet: Temel String Fonksiyonları6Bellek Yönetimi
Stack ve Heap BellekDinamik Bellek Ayırma - malloc()Bellek Ayırma için sizeof() KullanımıBellek Ayırma Hatasını Kontrol Etmefree() ile Belleği Serbest Bırakmacalloc() ile Bellek AyırmaÖzet: Dinamik Dizi