C++ "Segmentation fault (core dumped)" Hatası, çoğu durumda geçersiz bir bellek erişimiyle ilişkilendirilen sonlandırma belirtisidir. Çözüm, mesajı tek başına yorumlamak değil, geçersiz bellek erişiminin yerini, sınırını ve nesne yaşam süresini adım adım daraltmaktır.
İlk incelemede dizi veya std::vector indeksini, pointer ve referansların gerçek hedefini, nesnelerin erişim anında hâlâ yaşayıp yaşamadığını kontrol et. Aynı belirti farklı bellek hatalarından çıkabildiği için tek bir düzeltme her durumda işe yaramaz.
“Segmentation fault (core dumped)” Hatası Ne Anlama Gelir?
“Segmentation fault” ifadesi, Linux'taki sinyal adlandırmasında geçersiz bellek başvurusu anlamındaki SIGSEGV ile ilişkilidir. Program geçerli olmayan bir bellek bölgesini okumaya veya yazmaya çalıştığında bu sinyal üretilebilir ve süreç sonlandırılabilir. Mesaj, hatanın dizi sınırında mı, nullptr dereference işleminde mi, yoksa yaşam süresi sona ermiş bir nesnede mi başladığını tek başına göstermez.
“core dumped” bölümü, sonlandırma sırasında çekirdek dökümü mekanizmasıyla ilgili bir bildirimi ifade eder. Bu bildirim, dökümün mutlaka diske yazıldığını veya çalıştığın klasörde core adlı bir dosya oluştuğunu garanti etmez. Dökümün yazılıp yazılmaması, nereye aktarılacağı ve dosya adının nasıl belirleneceği kaynak sınırlarına ve sistem yapılandırmasına bağlı olabilir. Linux'ta varsayılan adlandırma core olsa da farklı bir ad veya konum kullanılabilir; bazı ortamlarda döküm bir toplama hizmetine aktarılabilir ya da kalıcı dosya olarak saklanmayabilir. Kabuğun gösterdiği metin de çalışma ortamına göre değişebilir.
Bu yüzden hata metnini teşhis sonucu değil, inceleme başlangıcı olarak ele al. Erişimin hangi adreste gerçekleştiğini, bu adresin hangi nesneye ait olması gerektiğini, erişimin nesnenin sınırları içinde kalıp kalmadığını ve nesnenin o anda canlı olup olmadığını birlikte sorgula.
C++ Bellek Erişimi Hatalarının Yaygın Nedenleri

Bu hata tek bir bellek kusurunun adı değildir. Aynı sonlandırma, yanlış indeks, hedefsiz pointer veya yaşam süresi bitmiş bir nesne gibi farklı senaryolardan çıkabilir.
- Dizi ya da
std::vectorsınırını aşmak: Üç elemanlıint a[3]veyastd::vector<int> v(3)için geçerli indeksler 0, 1 ve 2'dir.a[3]ya dav[3]koleksiyonun dışında bir konuma yönelir. Dizi veya vektör erişim anında hâlâ yaşıyor olsa da bu konumda geçerli bir eleman yoktur. Buradaki neden, nesne yaşamı değil sınır ihlalidir. nullptrdereference:int* p = nullptrhiçbir nesnenin adresini taşımaz.*pveyap->alankullanıldığında erişilecek canlı hedef yoktur. İndeks aralığı söz konusu değildir, sorun doğrudan hedefin bulunmamasıdır.- Başlatılmamış pointer:
int* p;bildirimi,p'nin belirli bir nesneyi gösterdiğini garanti etmez. Böyle bir pointer'ı adres gibi kullanmak veya dereference etmek, hangi nesneye yöneldiğini ve erişim anında canlı bir nesne bulunup bulunmadığını belirsiz bırakır. İndeks kontrolü bunu düzeltmez. - Serbest bırakılmış ya da başka biçimde geçersiz pointer:
delete psonrasındap'nin eski adres değerini taşıması mümkün olsa bile o adresteki nesnenin yaşamı sona ermiştir. Depolama başka bir amaçla kullanılmış olabilir. Benzer biçimde,std::vectoryeniden tahsis yaptığında daha önce alınmış eleman adresleri geçersizleşebilir. Bu durumda indeks doğru görünse bile pointer artık yaşayan bir elemanı göstermeyebilir. - Fonksiyon dönüşünden sonra kalan pointer veya referans:
int& f() { int x = 5; return x; }örneğinde adres yerelxnesnesine aittir. Fonksiyon bittiğindex'in yaşamı sona erer ve dönen referansın yöneldiği canlı nesne kalmaz. Aynı durum, yerel değişkenin adresini döndüren pointer için de geçerlidir. Burada indeks değil, nesne yaşam süresi belirleyicidir. - Yaşam süresi sona ermiş nesnenin üyesine erişmek: Bir nesneyi yöneten sahip nesne yok edildiğinde ondan alınmış ham pointer depolama adresini tutabilir, ancak artık geçerli bir nesneyi göstermeyebilir. Bu pointer üzerinden
p->alançağırmak, erişim anında ilgili türden canlı bir nesne bulunmadığı için hatalıdır. Burada indeks aralığı değil, nesnenin yaşamda olup olmadığı önemlidir.
Bu senaryolar C++ açısından tanımsız davranışa girebilir. Program bir çalıştırmada hemen sonlanırken başka bir çalıştırmada yanlış değer üretebilir, farklı bir satırda çöker veya görünürde çalışıyor gibi davranabilir. Daha önceki bir bellek bozulması varsa görünen son satır yalnızca etkinin ortaya çıktığı yer olabilir. Bu nedenle adres, sınır ve yaşam süresi birlikte incelenmelidir.
Kaynağı Bulmak İçin Üç Adımlı Teşhis Çerçevesi

Segmentation fault kaynağını bulmak için kodu rastgele değiştirmek yerine erişim noktalarını sırayla daralt. Karar akışı; erişimi belirleme, sınırı doğrulama ve nesnenin yaşam süresini kontrol etme aşamalarından oluşur.
Erişimi belirle
Önce programı küçük bir parçaya indir ve hatanın oluştuğu satıra gelen veri akışını izle. Dizi erişimlerini, *pointer kullanımlarını, pointer->alan ifadelerini ve fonksiyonlardan dönen referansları işaretle. İndeks, pointer ve referans değerlerini erişimden hemen önce gözlemlemek, hatanın hangi veriyle ortaya çıktığını gösterir. Hata ayıklayıcı, bellek denetim araçları veya derleyici uyarıları bu aşamada yardımcı olabilir; ancak belirli bir araca bağlı kalmadan da küçük bir örnek oluşturabilirsin.
Sınırı doğrula
Dizi ya da vektör için indeksin alt ve üst koşulunu ayrı ayrı incele. İlk geçerli indeksin 0, son geçerli indeksin size - 1 olduğunu kontrol et. Sınırın hemen dışındaki size değerini ve indeks türü uygunsa negatif değerleri de ayrı dene. Pointer'ı *ptr veya ptr->... ile kullanmadan önce ptr == nullptr kontrolü yap. Başlatılmış bir pointer'ın değerini veya adresini dereference etmeden gözlemleyebilirsin. Pointer'ın nullptr olmaması, onun mutlaka geçerli olduğu anlamına gelmez.
Yaşam süresini kontrol et
Referansın veya pointer'ın işaret ettiği nesnenin gerçekten oluşturulup oluşturulmadığını, doğru türde olup olmadığını ve erişim anında hâlâ yaşayıp yaşamadığını incele. Bir fonksiyonun yerel değişkenine ait referansın fonksiyon dönüşünden sonra kullanılması, kapsamı sona ermiş bir nesnenin adresine erişilmesi veya başlatılmamış bir pointer'ın okunması bu aşamada değerlendirilir.
Her değişiklikten sonra aynı hatayı yeniden üret ve sınır durumlarını tek tek karşılaştır. İndeks, pointer ve nesne yaşam süresi kavramlarını birlikte değerlendirmek için yazılım bilgi testleri merkezindeki Algoritmik Düşünme Testi, tekrar etmen gereken temel konuları belirlemene yardımcı olabilir.
Dizi Erişimini Güvenli Sınır Kontrolüyle Düzeltme
Üç elemanlı bir vektörde geçerli indeksler 0, 1 ve 2 değerleridir. Bu nedenle index = 3 iken korumasız values[index] erişimi sınırın dışında kalır. Erişimden önce alt ve üst koşulları denetleyen örnek şöyledir:
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{10, 20, 30};
int index = 3;
if (index >= 0 && index < static_cast<int>(values.size())) {
std::cout << values[index] << 'n';
} else {
std::cout << "Geçersiz indeksn";
}
return 0;
}
Koşul sağlanmadığında values[index] çalıştırılmaz ve program dizi dışındaki belleğe erişmeyi denemez.
Beklenen çıktı: Geçersiz indeks
Bu kontrol yalnızca dizi veya vektör sınırı sorununu ele alır. nullptr dereference, geçersiz pointer ya da yaşam süresi sona ermiş bir nesne için ayrıca pointer ve nesne yaşam süresi kontrolleri gerekir.
Üç Maddelik Hızlı Kontrol Listesi
Hata ayıklama sırasında şu üç kontrolü sırayla uygulayarak şüpheli bellek erişimini daha kolay daraltabilirsin:
- Çökmenin gerçekleştiği şüpheli erişimi belirle ve o anda kullanılan indeks, pointer ya da referans değerini doğrudan kontrol et.
- İndeksin geçerli sınırlar içinde olduğunu, pointer'ın
nullptrolmadığını ve gösterdiği belleğin hâlâ geçerli olduğunu doğrula. - İlgili nesnenin yaşam süresini kontrol et ve sınır değerleriyle boş veri gibi durumları yeniden deneyerek aynı veri akışını tekrar çalıştır.
Bu kontrolleri yalnızca C++ sözdizimine bakarak değil, verinin hangi koşullardan geçerek erişim noktasına ulaştığını inceleyerek yap. İndeks, koşul ve veri akışını dilden bağımsız değerlendirmek için Algoritmik Düşünme Testi gibi çalışmalar da yararlı bir değerlendirme çerçevesi sunabilir. Düzeltmeden sonra küçük bir örnek üzerinde normal akışı ve sınır durumlarını ayrı ayrı yeniden dene.
Sık Sorulan Sorular
Segmentation fault derleme aşamasında mı, çalışma zamanında mı oluşur?
Segmentation fault, program çalışırken oluşan bir bellek erişimi hatasıdır. Derleyici bazı riskli kullanımları uyarı olarak gösterebilir; ancak geçersiz erişim, pointer kullanımı veya nesne yaşam süresi gibi sorunların bir bölümü ancak program ilgili kodu çalıştırdığında ortaya çıkar.
Hata mesajında görünen satır neden kök nedeni göstermeyebilir?
Görünen satır, bellekteki bozulmanın başladığı yeri değil, geçersiz erişimin fark edildiği noktayı gösterebilir. Pointer daha önce bozulmuş, indeks yanlış hesaplanmış veya ilgili nesnenin yaşam süresi sona ermiş olabilir. Bu nedenle değerin üretildiği veri akışını da geriye doğru incelemek gerekir.
Dizi sınırı kontrolü pointer ve nesne yaşam süresi hatalarını da çözer mi?
Hayır. Sınır kontrolü, indeksin uygun aralıkta olup olmadığını değerlendirir. nullptr, geçersiz pointer veya yaşam süresi sona ermiş nesne sorunları için pointer'ın geçerliliğini, nesnenin sahipliğini ve kullanım anındaki yaşam süresini ayrıca kontrol etmelisin.
Her düzeltmeden sonra küçük bir örneği farklı sınır durumlarıyla yeniden çalıştırarak erişim, koşul ve nesne yaşam süresinin birlikte doğru ilerlediğini gözlemle.