Acaba ortam değişkenlerinde tanımlı yollar içinde karışıklık oluşturan kütüphaneler mi var?
Ben mesela, bu kütüphane yollarının hepsini devre dışı bırakıyorum çünkü mingw’nin kendi ortam değişkenleri ile windows’un ortam değişkenlerine eklediğim kütüphaneler karışıyor.
Bakın mesela burada msys64\mingw64\bin klasörünü devre dışı bırakmışım. Qt’yi de aynı şekilde devre dışı bıraktım çünkü uyumsuzluk oluşturuyorlardı. Doğrudan msys konsolunu ve msys’nin ortam değişkenlerini kullanıyorum.
free esnasindaki patlamalar, malesef %95 kodun baska yerindeki hatalardan kaynakli oluyor. Stack’teki bir pointer degerinin bozulmasindan dolayi olabilir, ki bu da C/C++'taki hatalarin hemen hepsinin olasi bir sonucu. “Muhtemelen UB var” da diyebilirim, ama bu da onceki iki cumle kadar genis ve yardimci olmayan bir bilgi olur.
Kodunuz compile olurken aldiginiz uyari mesajlarina dikkat etmeniz lazim. Hatta burada paylasmaniz faydali olabilir. (Kodunuzu butun uyarilar acik compile ediyorsunuz, degil mi?)
Kodunuzu debug modunda derleyip calistirmak da bir suru UB’nin bulunmasina yardimci olur. Mesela her array access’in array sinirlari icerisinde oldugunu kontrol eden kod bir suru dilin/compiler’in debug modunda programa ekleniyor. Daha gecen gun MSVC’nin her fonksiyon cagrisinin sonunda stack’i kontrol ettigini ogrendim. Bir fonksiyonu yanlis calling convention ile yazdigimi fark etmemi sagladi.
Bunun disinda Qt baglantili bir problem olabilir. (Atiyorum) “bu class ve cocuklarindan sadece cift sayida yaratilmalidir” gibi dilin hata/uyari mekanizmalari tarafindan denetlenemeyecek bir gereksinim cigneniyor olabilir. Boyle durumlar dokumentasyonda dikkat cekici sekilde belirtilir genelde, kullandiginiz parcalarin dokumentasyonunu tekrar okumak faydali olabilir.
Debug etmek icin alloc/free islemlerini takip eden, Valgrind gibi bir tool kullanmayi deneyebilirsiniz.
Bozuk pointer’in hangi objeye isaret ettigini/hangi fonksiyonda yaratildigini bulup programin omru boyunca izleyebilir, veya memory breakpoint koyarak nerede bozuldugunu bulmaya calisabilirsiniz. Hatanin kaynagi oraya yakin olacaktir.
Ortam değişkenleri birbirine girmiş Ben vakti zamanında C/C++ programlarını windowsta test etmeye işim düştüğünde sourceforge’dan mingw tool’larını indirmiştim. Daha sonra msvc’yi keşfetmiştim. Daha da sonra w64devkit’i keşfetmiştim. Öncekileri path’ten temizlemeyi unutmuşum. Windows’a nadiren girdiğim için onları çoktan sildim sanıyorum ben. Hatta choco’dan make tool indirmişim bir tane, belki eski sürüm falandı, o da path’teydi. Neyse, artık yoklar :D Problemi çok yanlış yerlerde aramışım. w64devkit terminalinde birebir linuxta test ettiğim gibi çalışıyor şu anda. Teşekkür ederim. Bu arada programa dair farklı geri bildirimleriniz olursa merak ederim.
@aib İleriki çalışmalarımda bahsettiklerinizi mutlaka dikkate alacağım. Çözümü basit bir problem sayesinde aib postu okumuş oldum :)
Araştırma yaparken sahiden burada bahsettiğiniz gibi durumlara internette farklı farklı şekillerde rastladım ve şunu düşündüm: Ben basit bir programda bile segfault hataları ile boğuşamıyorum, telegram gibi qt programlarını yazan insanlar acaba bu tür problemleri nasıl aşıyorlar? Ara ara meraktan telegramın kodlarını okuyorum. Kitap gibi yazmışlar, derli toplu. Biraz da ondan merak uyandırıyor herhalde. Sizin yazdıklarınızdan yola çıkarak bu tür problemleri aşmada tecrübenin önemli olduğunu fark ediyorum. Muhtemel problemlerin nerelerden kaynaklandığına dair hızlıca tahmin yürütmüşsünüz. Benim bildiğim veya daha doğrusu tahmin ettiğim kadarıyla insanlar disassembler tool’ları ile programları assembly kodları şeklinde okuyup bu gibi hataları saptıyorlar. Bu tarz debugging işlerinde assembly okuma kültürüne sahip olmayı önemli bir avantaj olarak görüyor musunuz? Veya soruyu daha genel ve doğru bir şekilde yönelteyim: Bu tür debugging çalışmalarında kendimi geliştirmek için neler yapabilirim?
Kendi sorunuzu cevaplamissiniz. Kodu kitap gibi, derli toplu yazinca hata yapmasi zorlasiyor. Hatalar goze farkli fontla yazilmis yazi gibi batabiliyor. (Malesef alisilagelmemis, kutuphane yazarlarinin, dil gelistiricilerinin ongorememis oldugu hata olmayan seyler de goze batabiliyor.)
Tecrubenin genel ve ozel olan iki hali var. Ozel, Qt’yi bilmek. Sinyal baglantilarinin nasil yapildigini, abzurt makrolarin nasil kullanildigini, kodun nasil duzenlenmesi gerektigini bilmek. (Yukaridaki sacma ornekten) hangi class’lardan cift sayida yaratilmasi gerektigini bilmek.
Bir de genel tecrube var, bu da mesela burada benimki. Qt bilmem ama grafik kutuphanesi cok kullandim, debugger kullanmayi biliyorum, cok UB avladim… Her zaman hizli sonuc vermese de probleme yaklasma yontemleri sunuyor. En kotu halinde, spesifik tecrubeye sahip birinin saniyede “sundandi” diyecegi seyi saatlerce avlamaniz gerekebiliyor. Avantaji ise, cogu problemde kullanilabilmesi.
Assembly seviyesine kadar inmek C/C++ gelistirirken bile nadir bir durum. Experimental veya ilginc compiler ozellikleri kullanilmadikca, sorun build asamasinda olmadikca, [sorun] koddaki satirlara bagli oldugu icin, kaynak kodu uzerinden takip edilebiliyor ve cozulebiliyor.
Bence hata ayiklamakla ilgili en onemli beceri printf ile hata ayiklayabilmek. Yani koda gecici, takip amacli “su fonksiyon cagrildi”, “v’nin degeri %f” gibi log satirlari ekleyip hataya dogru yaklasabilmek. Guzel log mesajlari yazma kulturu vermesinin yaninda, en kisitli calisma sartlarinda bile calisan bir yontem. Hatta genelde en son kaybedilen yontem. (Ilk kaybedilen, IDE’nin icindeki debugger mesela. Hata Release modunda veya baska bilgisayarda ciktigi anda gelistiricinin IDE’sinden debug edilemez oluyor.)
Onemli/buyuk bir avantaj olarak gormuyorum acikcasi. Nadir olarak gerektigi icin, her ortaya ciktiginda daha iyi bilen birinin basi agritilabilir. Cok daha onemli, pratik bilgiler var: Mesela RAII nedir, otomatik pointer’lar nasil kullanilir, veya “composition over inheritance” nedir gibi. Bunlarin bilinmemesi bahsedilen insanlarin basinin her gun agrimasina yol acabilir.
Ama herkesin sevdigi, ilgilendigi seyi ogrenmesi lazim. Cunku insanin sevdigi, ilgilendigi seyde ilerlemesi daha kolay, kotu olmasi cok zor. Buna “yetenek” diyorlar genelde.
Cok degisik becerilere, beceri kombinasyonlarina ihtiyac olabiliyor. Case in point: Ikinci reverse engineering isimi aldim. Debugger’da assembly instruction’larina, muhtelif hexadecimal sayilara bakmak icin para aliyorum. Objelerin bir calismadaki memory adreslerini not ettigim bir not defterim var.
Bu veya baska sekilde debugging calismalarinda kendini gelistirmek icin… debugging yapabilirsin.
Basit fonksiyonlarin assembly’de neye benzediklerini biliyor musun mesela? push ebp bir sey ifade ediyor mu? or al, 1? (x86)
Yeterli C kodu disassembly’si okuduktan sonra C ↔ assembly cevrimi kafada oluyor.
C++ da oyleymis, gecen ay ogrendim. thiscall’u bilmek ve vtable’lara asina olmak gerekiyor sadece.
Pratik programlari yok mu? Reverse engineering/cracking icin CrackMe’ler var mesela. Belki kaynak kodundaki incelikte gizli hatalar icin DebugMe/FixMe’ler vardir. Olmadi uretiledebilir.
Burasi biraz daha aktif olsa milletin kodu disassemble/debug edilebilir.