Giriş
Bu yazının amacı, daha önce hiç debugger kullanmamış
kullanıcılara ya da kullanan kullanıcılara bu günlük
çalışma için daha hoş bir grafik ortam göstermektir. gdb
isimli debugger'ın yapabildikleri ve sağlamlığı hakkında
çok şey yazılabilir, ancak, her zaman olduğu gibi öğretici
amaçlar için bunları basitleştirmeye karar verdik :)
Debugger nedir?
" Bir zamanlar, tek işi kendi kodu içinde hata
bulmak için aşağıdakini kullanan bir programcı vardı:
/*Code*/
(...)
loop
change_a_variable;
show_value_of_variable;
end_loop
(...)
Çalışma zamanı içerisinde, değişkenlerin değerini
araştırabilmek için kaynak kodu içine bir çok kez bu
satırları eklemeye zorlanmıştı. Bu zor bir görevdi ve
programcının hayatını zorlaştırmaktaydı ve kendi kodunda
hataları bulmanın zahmeti, o kodu yazmanın zahmetini ikiye
katlıyordu.(..)".
Kim kendini daha önce böyle bir durumda bulmadı ki? Sık
sık programımızda hata oluşur, her şeyi değiştirmiş ve
herşeyi denemişizdir, denenecek az şey kaldığından bu
aşamada neredeyse derleyicinin hatalı olduğuna hemen hemen
kendi kendimizi ikna etmişizdir... İşte burada hata bulucu
yazılımlar devreye girer.
Debugger aşama aşama programınızın çalışmasını kontrol
etmenizi sağlar, bu şekilde değişkenlerin durumu,
tanımlanması, bazı koşullarda nasıl davrandıkları kolayca
takip edilebilir. Bütün bunlar, yine, program çalışırken
yapılır. Bu havada kalan tanımlama yeterince açık değilse,
bunu yazının ileriki aşamalarında daha açık hale getirmeyi
umuyorum.
Öykümüzde programcının spy isminde, aşağıdakileri
yapmasını sağlayan bir debugger'ı olsaydı neler olurdu:
jose# spy my_program
ve eğer spy'ı yardıma çağırdıktan sonra, programcımız
şunları yapabilseydi:
spy > execute my_program "up to line number
50"
spy > show me the value of the variable <X>
spy > what is the type of variable <X>
Muhtemelen, bu anda, hayali programcımız sevinçten
havalara uçmaktadır, çünkü en sonunda hatanın sebebini
bulmuştur.
Açıkça, spy adındaki elaygıtı çok kullanışlı olmuştu,
çünkü programcının programının çalıştığı sırada
değişkenlerin değerlerini ve tanımlanmalarını kontrol
edebilmesini sağlamıştır. Bu debugger'ın özüdür, ancak
tabii ki kabaca resimlendirilmiştir.
Dikkat !!: Debugger'lar sadece debug
parametreleriyle çalışan derleyiciler ile derlenen
programlar ile çalışır. GNU gcc derleyicisi örneğinde bu
parametre -g dir.
Tüm Linux kullanıcıları için GNU Genel Lisansı ile
elde edilebilecek GDB (The GNU Source-Level Debugger)
adında bir debugger vardır (bu değişik platformlarda da
bulunabilir). Bununla C, C++, Modula-2 ve assembler kodları
debug edilebilir.
Muhtemelen, şu anda kullandığınız Linux bu yazılıma
sahiptir, eğer değilse, Linux'ınızı yenileyin veya programın
kaynak kodunu bulun. Bu birçok yerde bulunabilir;)
Diyelim ki, /usr/src dizini altına kaynak kodlarını
kopyaladınız, sonra /usr/src/gdb-4.xxxx/gdb dizini altına
gidin ve doc dizinine inin. Orada make gdb.dvi;make
refcard.dvi komutunu kullanarak gdb dokümanlarını
oluşturabilirsiniz. Bu dosyalar tüm linux sürümlerinde
kolayca görüntülenebilir.
DDD nedir?
Gdb'nin ayrıntılı sunumu ve tüm komutlarını açıklamak
yerine, kullanıcı tarafından çok daha kolaylıkla
kullanılabilecek olan ddd (Display Data Debugger) isimli
ortamı açıklamak, yeni kullanıcılar için çok daha anlamlı
olacaktır.
DDD ortamı, genellikle konuşan, ayarlanması çok daha
kolay olan ve hata bulma için kullanıcıya daha anlaşılır
bir arayüz sunar. Yine de, belirtilmelidir ki, ddd sadece
gdb üzerinde kullanılan bir grafik ortamdır. Bu nedenle
ddd'nin çalıştırılması için gdb'ye gereksinim vardır.
Aslında, ddd kullanıcının gdb üzerinde doğrudan değişiklik
yapmasına izin vermektedir. DDD ile kullanılabilen dbx, xdb
gibi başka debugger'lar da vardır.
DDD için iyi bir bilgi kaynağı http://www.cs.tu-bs.de/softech/ddd/
adresinden elde edilebilir. Ayrıca, eğer RedHat
kullanıyorsanız kaynak kodlarını rpm formatında
bulabilirsiniz. DDD'nin iki ayrı sürümünü bulabilirsiniz,
Motif kitaplıklarıyla dinamik olarak derlenmiş sürümü,
diğeri ise statik olarak derlenmiş sürümüdür. Statik
sürüm kendi Motif kitaplüklarü olmayan kullanıcılar
içindir.
DDD'nin LESSTIF(http://www.lesstif.org)
karşısındaki şu andaki durumunu dikkate almıyorum. Motif'in
ücretsiz bir benzeri olan lesstif'in şu andaki durumu
hakkında pek bilgi sahibi değilim. Kısa bir zaman önce, bir
yama sayesinde sadece lesstif altında derlenebiliyordu. Bunu
1.2.13 çekirdek ve lesstif 0.75 ile kullandım (Sanırım ;).
Lütfen, lesstif projesinin sayfalarına bu proje ile ilgili
daha fazla bilgi almak için bir göz atınız.
İşe girişiyoruz, ddd'yi çalıştırmamızla birlikte,
şununla karşılaşıyoruz:
Resim 1: DDD ana ekranı
ddd'yi çağırmanın üç değişik yolları vardır;
ilkinden daha önce bahsetmiştik ve diğerlerini de aşağıda
bulacaksınız:
ddd <program> core
ddd <program> <process_id>
Core isimli dosya bir program çöktüğü zaman üretilir
ve çöküşün sebebi ile ilgili hatanın oluştuğu sıradaki
programın durumu ile ilgili yararlı bilgiler içerir. Eğer
sizin sisteminiz core dosyaları yaratmıyorsa, core
dosyaları için çevre değişkenlerine bir göz atınız ('ulimit
-a' hepsini gösterir, ya da 'ulimit -c <değer>' diğer
gerekli değerleri veya maksimum boyutları gösterir).
Proses id çalışma zamanı sırasında programı incelememizi
sağlar.
ddd'nin grafik yapısı bir işi yapmak için birden fazla
yol sunar; Burada hepsini açıklayamam, ancak en basit
olanlarını açıklayacağım. DDD'nin ana konsolunun en
altındaki pencere, ddd'nin çalıştırdığı tüm işlemlerin
loglarını gösterir. Bu log penceresi gdb'nin komut satırından
çalıştırılmasını öğrenmede çok yararlı olabilir.
GUI ortamı
1. resim ana pencerenin 3 alt pencereye bölündüğünü
gösteriyor. En alttaki alt pencere yalın debugger
consoludur (bizim durumumuzda bu gdb'dir). Burada, eğer ddd
arayüzümüz olmasaydı burada doğrudan gdb komutlarını
kullanabilirdik. Ortadaki alt pencere ise programın kaynak
kodunu göstermektedir, ve üst alt pencere ise programın
değişkenleri ve nesneleri için grafik bir ortamdır. Son
olarak ise, araç barı (toolbar) ddd komutlarının
çalıştırılmasının kontrolünü sağlar.
Ana pencere dışında ise çalışan proses için bir ve debug
edilen programın kaynak kodu için de ayrı birer pencere
vardır. Bunların ikisi de isteğe bağlıdır.
ddd ile birlikte, hata bulma sırasında gerekebilecek
yardım için tüm kaynaklar gelmektedir. Örnek vermek
gerekirse, imleç arayüz üzerinde bir değişken üzerine veya
arayüz üzerindeki herhangi bir butonun üzerine geldiğinde
ayrı bir dialog kutusu ekrana gelir; bu dialog kutusu o
andaki durumla ilgili gerekli bilgi verir. Ayrıca, ana
pencerenin alt tarafında ise, ddd'nin durumu, hangi komutun
çalıştırıldığı ve o komutun çıktılarını göstermektedir. Sağ
tarafta her türlü yardıma bir popup menü sayesinde
ulaşılabilir. Açılan pencerede bir konu seçip F1 tuşuna
bastığınızda daha fazla bilgi elde edilebilinir. Son olarak
gdb konsoludan "help" yazarak debugger hakkında genel yardım
veya belli bir konu üzerinde yardım alınabilir.
Benimsenmiş olarak, ddd tek çerçevede birleşmiş üç alt
pencere sunmaktadır. Ayrıca, "Preferences" menüsü ddd
arayüzüne benimsenmiş şekil yerine ayrı pencereler
açtırabilir.
Resim 2. File menüsü için yardım
Dipten başlangıç
Debugger konsolu, debugger2ın kullanımı öğrenmemizde
ilk adımlarımızı atacağımız yerdir; gdb üzerinde deneyimli
kullanıcılar ddd ile buradan çalışabilirler. Benim
durumumda bu konsol grafik arayüz üzerinden komutlar
çalıştırıldıkça neler olduğunu izleyebilmem için yardımcı
olmuştu. Commands-Command History seçimi o ana kadar
çalıştırılmış tüm komutları listeler.
DDD'nin yapabileceklerini öğrenebilmek için orijinal
dokümanlara bakmak daha yararlı olacaktır. Her durumda
debugger ile bir kaç basit işlemin nasıl yapılabileceğini
açıklayacağım.
Genel Görevler
Hata bulmak için, kaynak kodu yükleme işlemi menülerden
File seçeneği seçilerek yapılabilir; kaynak kodunun içeriği
bu alanda görüntülenir. Bu aşamadan itibaren, kaynak koduna
göz atarak, bir değişkenin değeri ve tipi incelenebilir ve
program kontrol altında çalıştırılabilir...
Programın çıktısı bir pencere ile izlenebilir ( Options
menüsünden Run in Execution window ) veya debugger
konsolundaki program çıktısından doğrudan izlenebilir ( bu
yöntem program Motif veya başka bir GUI tabanlı
kitaplıklar kullanıldıysa işe yaramaz).
Kaynak kodu içinde imleci herhangi bir değişken üzerine
getirmeyi denerseniz, o değişkenin o andaki değerini ddd
çıktısı içerisinde görebilirsiniz. Ayrıca, sağ fare butonuna
tıklarsanız aşağıdaki menü çıkacaktır:
Bu menü fname isimli değişkenin değerini incelememizi
sağlar, alttaki pencerede, çizim bölgesinde bu değişkenin
bir işaretleyici veya gerçek bir değişken olup olmadığı
gösterilir (işaretleyici başka bir değişkenin bellekteki
adresini saklayan başka bir değişkendir). What is bölümü
ise seçilmiş değişkenin yapısını veya tipini gösterir.
Lookup rastlanan benzerlikleri takip etmemizi sağlar. Son
olarak, Break at ve Clear at bölümlerinde kısaca anlatacağım
breakpoint diye deyimlendirilen kullanımlardır.
Kaynak kodun altındaki düğmelerin bulunduğu barda da
değişik seçenekler mevcuttur, sadece gerekli parametreleri
soldaki boş kutuya yazıp gerekli eylemi seçmek yeterlidir.
Bir break-point, programı istediğiniz satırına kadar
çaılıştırmanızı sağlar; belli bir noktada programın
çalışması durur ve kullanıcı değişkenlerin bu noktadaki
değerlerini izleyebilir. Ayrıca, bu noktadan sonra
kullanıcı programın çalıştırılmasını elle adım adım
yaptırabilir, ve aşama aşama programı izleyebilir.
Breakpointlerin olmaması durumunda, program problemsiz
çalışır veya bir hata sonucu çalışamadan sona erer,
bu durumda programı incelemek için bir işlem yapmak için
çok geçtir. Program çalıştırıldığı sırada hata bulma
işleminden geçirilmelidir.
Programınıza bir breakpoint eklemek için aşağıdakileri
yapınız:
- Breakpoint koymak istediğiniz bölümün sol tarafına
imleci getirip sağ fare butonuna tıkladıktan sonra Set
Temporary Breakpoint seçeneğini seçmeniz yeterli olacaktır.
İkisi arasındaki fark geçici olan breakpointlerin ilk
çalıştırmadan sonra kaybolmasıdır. Diğeri ise sadece
doğru komut verilirse kaldırılabilir (Bu komutu tahmin
edebilir misiniz? :) ).
- Break at isimli butonu kaynak kodu penceresinden
seçerek
- Debugger konsolundan break yazarak
- Menü seçeneklerinden Source->Edit Breakpoints
bölümünü seçerek, bu ayrıca bu programın kullanımı için
ayrı bir pencerede açacaktır.
Resimde 70 ve 71. satırlarda, kaynak kodu içinde iki
breakpoint görünmektedir. Breakpoint için kullanılan sembol
kendi kendini çok iyi açıklamaktadır.
Aşağıdaki menü breakpointleri kullanmaya yarar:
- Condition seçeneği ile, koşullu breakpointler
yerleştirilebilir. Bu durumda, programın breakpoint
satırında durması için koşulun gerçekleşmesi gerekir.
Başka bir koşul çeşidi ise Ignore Count seçeneğidir.
Bu durumda, koşulun doğru olması için breakpoint
satırına <n> defa ulaşılması gerekir.
Örneğin, herhangi bir döngünün 15. iterasyonundan sonra
programı durdurmak için kullanılabilir.
Program herhangi bir breakpointte durduğunda, gerekli
menülerin seçeneklerini kullanarak programdaki değişkenlerin
değerlerini inceleyebiliriz. Bütün bu fonksiyonlar ana menüde
bulunmaktadır (örnek; menu Data).
-
Kodun çalıştırılmasını kontrol etmek amacıyla, bu iş için
kullanılan düğmelerin bulunduğu pencereyi kullanacağız. Bu
pencere ana pencerenin sağ üst köşesinde bulunmaktadır.
Menü bar ile düğmelerin bulunduğu pencere arasındaki benzerlik
görülebilir.
Programı çalıştırıp durdurabiliriz, menü barının kullanılması
durumunda, dialog penceresini kullanarak programa bazı parametreler
vermek olasıdır. Step komutu, programı satır satır çalıştırır, bu
durumda, programın herhangi bir yerinde bir fonksiyon çağırılırsa,
hata bulucu o fonksiyonun başına gidecek ve bir sonraki Step
komutunu bekleyecektir. Öte yandan, Next komutu ise,
fonksiyonları tek satır olarak kabul eder ve bu işlemleri tek
aşamada yapar.
Continue komutu, herhangi bir breakpointte durulduktan
sonra programın çalıştırılmasına devam edilmesini sağlar. Kill,
Interrupt, Abort komutları ise programın çalıştırılmasını
durdurmak için kullanılır.
Muhtemelen, bu grafik ortamın en önemli özelliği, pencerenin üst
tarafında bulunan bilgi gösteren penceredir. Grafiklerle, bilginin
yapısını, içeriğini ve diğer bilgiler ile arasındaki bağlantıları
buradan izleyebiliriz. Bir sonraki örnekte, bir dizi (argümanlar)
ve o dizinin dört elemanı görülmektedir.
Bu pencere, çok geniş bilgi sunar, Data->More Status
Displays bölümünden yapılabilecek ayarlarla, data penceresinde
görmek istediğiniz herşeyi ayarlayabilirsiniz. Bir önceki örnekte,
işlemcinin kayıt değerlerini, gerekli dinamik kitaplıkları ve
programın çalışma durumunu görebilirdik:
Son Sözler
DDD ortamı, aynı program kullanılarak, Options->Preferences
menüsünden ayarlanabilir. Ayrıca, bu ayarlar Motif programlarının
klasik yöntemi olan $HOME/.dddinit dosyasından da yapılabilir.
Ayarlanabilecek tüm kaynakların açıklanması bu yazının dışındadır.
DDD ile gelen kitapçığın (ddd.ps)ve hata bulucunun kitapçığının
(Debugging with GDB) okunması çok önemlidir. Yine de, kullanıcı
bunları kısa bir zaman içinde kendi kendine de öğrenebilir.
Yapılamsı gereken sadece iyice tanıdığınız bir kodu burada hata bulma
işlemine tabii tutmanızdır. Bu şekilde hata bulucunun yapabilecekleri
ortaya çıkacaktır.
Ve son olarak, yazıda hatalar yaptıysam özürlerimi sunarım :)
|
|