İçeriğe geç

Menü

Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

C++ "Segmentation fault (core dumped)" Hatası Nasıl Çözülür?

cpp-segmentation-fault-core-dumped-hatasi-nasil-cozulur
Bu yazıda neler var?
  1. “Segmentation fault (core dumped)” Hatası Ne Anlama Gelir?
  2. C++ Bellek Erişimi Hatalarının Yaygın Nedenleri
  3. Kaynağı Bulmak İçin Üç Adımlı Teşhis Çerçevesi
  4. Dizi Erişimini Güvenli Sınır Kontrolüyle Düzeltme
  5. Üç Maddelik Hızlı Kontrol Listesi
  6. Sık Sorulan Sorular

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

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::vector sınırını aşmak: Üç elemanlı int a[3] veya std::vector<int> v(3) için geçerli indeksler 0, 1 ve 2'dir. a[3] ya da v[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.
  • nullptr dereference: int* p = nullptr hiçbir nesnenin adresini taşımaz. *p veya p->alan kullanı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 p sonrasında p'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::vector yeniden 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 yerel x nesnesine aittir. Fonksiyon bittiğinde x'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

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:

  1. Çö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.
  2. İndeksin geçerli sınırlar içinde olduğunu, pointer'ın nullptr olmadığını ve gösterdiği belleğin hâlâ geçerli olduğunu doğrula.
  3. İ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.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara