Aslında günümüzdeki en büyük sorunlardan biri C++'ı sıfırdan başlanmış bir projede yanlış kullanıyor olmak değil, bağımlı olunan SDK'lardaki tavsiye edilenin dışındaki kullanımlar neden oluyor. Yani belli bir sistematiğe sahip yazılım ekipleri, kendi uygulamalarını, kütüphanelerini, SDK'larını çok düzenli geliştirebilir ve C++'ın hedef olduğu eleştirilere gülüp geçebilirler. Ancak C++'dan şikayetçi olmakta haklı olan ekipler de var, şahsen de bu tür durumlara maruz kaldığım oldu.
En sık yaşanan durumlardan biri şu. Aynı SDK'nın içinde, bir fonksiyon char*, diğeri LPCSTR, bir diğeri LPCWSTR, ötekisi OLESTR istiyebiliyor. Hadi bu wrapper yazmaya alışık kişiler için hızlı aşılabilecek sorunlar ancak daha vahim kullanımlar da gördüğüm oldu. Mesela "char* filepath" tarzı bir parametre oluyor ve sen haliyle "c:\\hede\\hodo" bir input veriyorsun. Sonuç? File not found. Sebebi ise adam senden char* istiyor ama aslında unicode string girmen gerekiyor. Tabii ki Çince (!) dökümanda bundan bahsetmeyi unutmuş olabiliyorlar.
Bunu geçiyorum, tersini de görüp epey şok olmuştum. Adam WCHAR ya da LPCWSTR gibi bir parametre bekliyor. Haliyle string'i unicode'a çevirip veriyorsun ve çalışmıyor. Ansi string'i unicode'a çevirmeden sadece pointer'ını cast edip verince çalışıyor.
Bunlar extreme durumlar ancak bunları yaşayınca insan "hay senin gibi..." diye birşeylere saydırmak istiyor. Ben SDK'yı yazanlara saydırmayı uygun görürken bazıları da dile saydırmayı tercih ediyor.
Yaşadığım ve hala tam mantığını anlayamadığım durumlardan biri de şu olmuştu. Bir SDK'da bir structure var. Atıyorum şöyle birşey;
struct Frame {
DWORD width;
DWORD height;
...
BYTE data[1];
}
Sondaki data[1] dediği şey tüm frame datasını tutacak olan yer. SDK'nın kendi örnekleri bile memory access violation veriyor. Adam 1 byte olarak belirlediği yere kilobytelarca veri girmeye çalışıyor, hiçbir allocation olmadan. Doğrudan pointerına dayıyor veriyi.
Nasıl oluyor bilmiyorum ancak merak edip denedim, Visual Studio 6'da bu bir biçimde çalışıyor. Yani çalışıyor derken safe biçimde çalışıyor anlamında değil ancak VC 6 runtimeları herhalde memory konusunda o kadar strict değilmiş ki program göçmüyor. Daha üst runtimelar böyle bir saçmalığa izin vermiyor. Elimle denemelik BYTE data[1] olan yeri BYTE data[20000] diye ortalama, en büyük paketi kapsayabilecek bir değerle değiştirdim ve yeni runtimelarla da çalıştı (tabii ki kalıcı bir çözüm olarak yapmadım bunu). ınsan kodları elinde olmadığı, direk lib'lerini linkleyerek kullandığı bir SDK'nın header dosyasını değiştirmek durumunda kalabilir mi?
Sonuç olarak C++'dan sıfırdan bir proje üretecekseniz ve bir bağımlılığınız olmayacaksa işiniz çok kolay. Ama başka birinin SDK'sına muhtaç durumdaysanız dua edin de o adamlar işini hakkıyla yapmış olsunlar.
Programcılığın dilden çok zor yanları genellikle şu şekildeki diyaloglarla benim hafızama kazınmıştır. Bu özel bir örnek değil, ilk aklıma gelen bu oldu.
- (birkaç gün kafayı sıyırdıktan sonra...) Ya cihaza komutları gönderiyorum, ilk komutu alıp diğerlerini almıyor. Komutların arasına biraz sleep koyduğumda alıyor. Dökümanda böyle bir durumdan bahsedilmemiş. Komutlar için bir queue mekanizmanız yok mudur? Ya da iki komut arası ne kadar beklemem lazım, ne önerirsiniz?
- 50-60 milisaniye kadar falan bekleyin... ya da 100.
- teşekkür ederim.
Ya da rekorlardan biri. Bir bug bulup, içime sinmeyen bir workaroundla çözdükten sonra firmanın teknik ekibiyle yazışmalarımdan bir kesit.
- Epey uğraştıktan sonra sorunun şurada olduğunu farkettim, şöyle bir workaroundla çözebildim. Ancak elbette ki bu geçici bir çözüm. Bu konuyu belki yeni SDK'nızda çözmüşsünüzdür diye öncelikle sizinle irtibata geçmek istedim. Bu konu yeni SDK'da çözüldü mü? Ya da bu sorunun çözümü için ne önerirsiniz?
- Bize örnek kodları gönderirseniz çözümü yeni SDK'mıza ekleriz.
şimdi söyleyin bana. C++'ın günahı ne?