11 Kasım 2008 Salı

C++ Dizi İşlemlerinde Dikkat Edilmesi Gerekenler

Bu yazıda C++ kullanıcıları için çok önemli bir şeye değineceğim. Bunu da edindiğim acı tecrübeden yola çıkarak yazıyorum. C++ bildiğimi zannederdim, okulda hocamızın verdiği ödevde uzun zaman sonra C++ kullanmam gerekiyordu. 2 gün boyunca boş zamanlarımda sadece char dizisini almaya ve bunu print etme işlemine çalıştım inanın. Bu ödevin önemli bir kısmını tamamlamış bulunuyorum :). Bu ödevi yaparken karşılaştığım ve yapılması yüksek ihtimal mantık hatalarından bahsedeceğim. Bu konulara hakim olup dikat etmeniz önemli. Bu sorunlarla ben karşılaştım başkaları karşılaşmasın. Bi göz atmanızı tavsiye ederim.
Aşağıda anlatacağım işlemlerde char* array = new char[20]; dizisini kullanacağım.

1 - Öncelikle 20 karakter tutabilecek bir diziye bellekten yer ayırdık. Şimdi buna array[0] = 'a'; değerini atayalım ve print edelim. a___-----_İİİ gibi anlaşılmaz şeyler print edecektir. Bunun için yer ayırdığımız dizinin her bir elemanını dolaşarak temizlemeliyiz.
for(int i=0 ; i<20;>i++)
{
array[i] ='\0'; // \0 null demektir.
}


2 - Şimdi bu diziye ilk değer olarak array[0] = 'a'; atadık. Biliyorsunuz ki dizinin son elemanından sonra null değeri vardır bu da dizinin bittiği anlamına gelir. O yüzden bu diziyi başka işlemlerde kullanacaksanız, sonunu null yapmazsanız hata alma olasılığınız çok yüksektir. Bunu önlemek için de verdiğimiz en son değerden sonraki değeri null yapmalıyız. Yani array[1] = '\0'; değerini mutlaka vermeliyiz.

3 - array[0] = '2' ile array[0] = 2 aynı şey değildir bunu çoğu kimse bilir yine de buraya ekleyip hatırlatmanın iyi olacağını düşündüm.

4 - Uzunluk ile ilgili problem. Programda int uzunluk = strlen(array); diye uzunluğu bulduk diyelim ve uzunluk = 5 olsun, dizinin de dolu olduğunu düşünelim. Dizide array[uzunluk] = 'a'; demek veya for döngüsü içinde
for(int i=0 ; i <= uzunluk; i++) {
array[i] ='a';
}
bu şekilde kullanmak programın runtime ında hataya sebep olacaktır. Çünkü diziler indis olarak 0 dan uzunluk - 1' e kadardır.

5 - Dizinin ilk 0 elemanının dolu olduğun düşünelim. 'ahmetuzun'. array[1] = '\0' yani dizinin ikinci elemanının değerini null yapıyoruz. Diziyi print ettiğiniz zaman ekrana gelen a olacaktır. strlen(array) in sonucu da 1 olacaktır. Yani dizi dolu olsa bile, null değerini koyduğumuz yerden sonraki veriler kaybolur.

6 - Şimdi yeni bir dizi tanımlıyoruz. char* temp = new char[20]; bu dizi genelde geçici bir dizi olarak tanımlanır ve işi bittiğinde silinir. temp dizisini tanımladık ve temp dizisine temp = array diyerek yukarıda tanımlamış olduğumuz diziyi atadık. Daha sonra temp dizisini kullandık ve delete[] temp; diyerek bu diziyi bellekte boşuna yer kaplamasın diye sildik.
Eğer bu şekilde yaparsanız array dizimizde silinir. Çünkü bu diziler referansa göre çağırılırlar. Yani çağırılan dizinin bellek adresine bakılır. temp = array demekle bu iki dizinin bellek adreslerini bir yapmış oluyoruz. Bu yüzden temp silinirse array de gider. Zaten görüldüğü üzere burada temp dizisiyle array dizisi bellekte aynı yeri kapladığı için silmeye gerek de yok.

Daha bu tarz yapılabilecek hatalar varsa eklerim. Sizlerin bildiğiniz bu tarz hatalar varsa onları da eklerim :D

1 Kasım 2008 Cumartesi

Traceroute

Yazmayalı uzun zaman olmuş ben bile şaşırdım kendime, yazmayınca içimde bir eksiklik hissettim. Her neyse konumuza dönelim.
İnternete herkes hayrandır şahsen ben hep şaşırırım nasıl bu kadar büyük bir ağ oluşturmuşlar ve bu ağ hiç takılmadan çalışıyor. İçinde çalışan protokoller ve application ları söylemiyorum bile.
İnternete girdiğmizde örneğin milliyet in sitesine tıkladığımızda acaba hangi router lar üzerinden geçip milliyetin server ına ulaştığımızı biliyor muyuz? Bunu öğrenmenin yolları var.
Traceroute sitesine girip bulunduğunuz ip adresini ve gitmek istediğiniz web sitesinin adını veya ip adresini yazdığınızda size nerelerden geçtiğini söylüyor. Bu nasıl çalışıyor anlatmayacağım çok uzun, fakat sonuçta bize bir şey dönüyor bu dönen verilerin ne olduğundan bahsedeceğim.
İkinci yol websitesine girmeye gerek kalmadan komut ekranından (dos) yapılabilir. Komut satırına şunu yazmamız gerekiyor [tracert www.milliyet.com.tr] Aynı işlemi yapacaktır.
Üçüncü yol program aracılığı ile PingPlotter. Bu program yardımıyla da trace işlemleriniz daha efektif bir şekilde yapabiliyorsunuz. Efektiften kastım ne yani, kaç defa trace yapacağımızı söyleyebiliyoruz, çıkan sonuçları grafiksel bir arayüzde görebiliyoruz ve bunları bilgisayarımıza kaydedebiliyoruz falan filan.
Sonuç olarak ne çıkıyor ona bakalım.
www.milliyet.com.tr [83.66.140.10]'ye izleme yolu :
1 89 ms 2 ms 1 ms 10.0.0.1
2 78 ms 76 ms 84 ms 192.168.1.1
3 56 ms 57 ms 86 ms 88.234.40.1
4 * * * istek zaman aşımına uğradı
5 85 ms 77 ms 85 ms 212.156.107.38
6 76 ms 58 ms 72 ms 81.212.25.109
7 78 ms 95 ms 93 ms 212.174.75.142
8 66 ms 61 ms 94 ms 83.66.140.10
Birinci kolon, ana server a ulaşmak için toplam kaç router dan geçtiğini belirtiyor.
İki, üç ve dördüncü kolon, yanında ip adresi bulunan routerlara geldiğinde, bu routerdan çıkabilmek için ne kadar gecikme süresi olduğunu belirtiyor. Bu izleme siz bir defa komutu yazsanız bile 3 defa yapılıyor. Sırasıyla, bu kolonlarda bulunan süreler de yapılan üç izlemenin sırasıyla gecikme süreleri.
Dördüncü kolon, geçtiği router ın ip adresi.
Eğer siz de denerseniz bu ip adreslerin yanında bir de ip adreslerine atanmış router ların isimleri vardır onları da görebilirsiniz.
Bu nerde işimize yarar diyelim bir web siteniz var ve siz ona ulaşamıyorsunuz veya çok geç ulaşıyorsunuz. Bu şekilde web sitenize ulaşıncaya kadar trace işlemi yaparsınız. Geçtiğiniz routerlarda bir problem olabilir veya router dan geçme süresi çok uzun olabilir. Sorunu saptayıp çözüme bir adım daha yaklaşırsınız.
Şunu da belirteyim. Bazı routerlarda firewall vardır ve trace işleminde bize bilgilerini vermez.