C Programlamada Debugging (Windows)

C ile yazdığım bir proje ile uğraşıyordum. Bu uğraşı esnasında bir hata aldım, hatanın makefile kaynaklı olduğunu düşündüm çünkü herhangi bir compiler hatası ile karşılaşmamıştım. Bu sebeple ilk başta hatanın kodda olmadığını varsaydım. Ancak makefile'da hiç hata yoktu. Sonrasında kullandığım bir fonksiyonda referans döndürmediğimi fark ettim. Bunu farketmem iki saatimi aldı 💩. Oysa debug yapsam bu kadar vakit kaybetmezdim.

Öncelikle belirtmeliyim, bu yazı Windows kullanıcıları için olacak zira Linux kullanıcıları için fazlasıyla anlatım mevcut. Aşağıdaki kaynaklarda Linux kullanıcıları için geçerli makalelere göz atabilirsiniz. 

Debugging için GDB

GDB bir GNU project debugger olarak tanımlanabilir. Debugger, bir programın çalışmasını denetlemek için kullanılan ayrı bir programdır. Bu sayede çalışma esnasında durdurma, devam etme uygulanabilir ve belirtilen kod satırlarında programın çalışma durumu kontrol edilebilir. Örneğin, bir değişkenin çalışma sırasında ne değer taşıdığını görmek gibi. Ayrıca program adım adım kod satırları çalıştırılarak line-by-line denilen kontrol sağlanabilir. Detaylar için ayrıntılı bilgiyi bu adresten(https://www.gnu.org/software/gdb/) edinebilirsiniz.

Bu debugger Linux dağıtımlarında kullanıldığı gibi Windows ve MacOS işletim sistemlerinde de kullanılabilmektedir.

GDB'yi MinGW Installation Manager ile Windows'a yükleyeceğiz. Windows üzerinde daha öncesinde manual compile yaptıysanız muhtemelen MinGW'yi yüklemişsinizdir. 

MinGW Installation Manager'i açtıktan sonra All Packages kısmından aşağıdaki resimde olduğu gibi gdb için gerekli paketleri işaretleyelim.

C Programlamada Debugging
İşaretleme yapıldıktan sonra pencerenin üst sekmesinde yer alan Installation Apply Changes seçeneğine tıklanır. Bu işlemden sonra yüklemenin gerçekleşmesini bekleyin ve bittikten sonra Windows terminali açın ve gdb -version komutunu girin. Eğer sürüm bilgisini görüyorsanız başarılı bir şekilde gdb yüklenmiştir.

GDB Kullanımı

GDB'yi kullanmak için öncelikle saçma bir hesaplama sonucu veren örnek program kodunu aşağıya ekledim:
#include <stdio.h>

int main(){

    for(int i=0; i < 10; i++){
        printf("merhaba %d\n", i);
    }

    int sum;
    
    for(int i=0; i <= 10; i++){
        sum += i;
    }

    printf("%d", sum);

    return 0;
}
Kod derlendikten sonra elde edilen program çıktısı ise aşağıdaki gibi:
C:\Users\gurb\Desktop\debugger>p
merhaba 0
merhaba 1
merhaba 2
merhaba 3
merhaba 4
merhaba 5
merhaba 6
merhaba 7
merhaba 8
merhaba 9
3641364
Programda on kere merhaba yazısı yazdırıldı sonrasında ise 0'dan 10'a kadar 10 dahil tüm sayılar tek bir değişkende toplandı ama çok saçma bir sonuç elde edildi. Aslında hata oldukça bariz ama yapılan bu hatayı gdb ile bulmaya çalışalım.

GDB'yi kullanmak için program kodunu -g flag ile derlemeliyiz. -g flag sayesinde debugging esnasında programa ait fonksiyon ve değişkenlerin isimlerini görebiliriz. Örnek konsol çıktıları aşağıdaki gibi:
C:\Users\gurb\Desktop\debugger>gcc -g -o p example.c

C:\Users\gurb\Desktop\debugger>gdb p
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
...
Reading symbols from C:\Users\gurbu\Desktop\debugger\p.exe...done.
(gdb)
Debugger isimli proje dizini içinde yer alan program kodu gcc -g -o p example.c ile derlendi. Sonrasında ise bu program debug edilmek için gdb ile çalıştırıldı. (gdb p)

run komutu girilir, yine aynı şekilde yukarıdaki çıktıyı elde ederiz fakat programımız sonsuz döngüye girmiş olsaydı yapmamız gereken ctrl+c'dir bu sayede programın nerede sonsuz döngüye girmiş olduğunu görebiliriz.

Bu program kodunda başlangıç komutumuz break main komutudur. Bu komut, main fonksiyonu çağrıldığında debugger'ı durduracaktır:
(gdb) break main
Breakpoint 1 at 0x40141e: file example.c, line 5.
Bunun yanında belirli bir satır numarasında da break işlemi uygulanabilir. Gerekli komut şu şekilde olmalı break fileName:lineNo. Eğer biz örneğimizde bunu uygulamak istersek break example.c:11 komutunu girebiliriz, buna göre debugger sırasında 11.satırda duracaktır.
(gdb) break example.c:11
Breakpoint 2 at 0x401448: file example.c, line 11.
Yukarıdaki gibi breakpoint belirtildikten sonra start komutu ile program başlatılır. Ancak daha öncesinde breakpoint belirtilmediyse program hızlıca başlayıp, sonlanacaktır.
(gdb) start
Temporary breakpoint 3 at 0x40141e: file example.c, line 5.
Starting program: C:\Users\gurbu\Desktop\debugger/p.exe 
[New Thread 2868.0x42d4]
[New Thread 2868.0x1704]

Breakpoint 1, main () at example.c:5
5           for(int i=0; i < 10; i++){
Sonrasında next komutu ile program adım adım çalıştırılır. Yine aynı şekilde next komutu yerine n komutu kullanılabilir:
(gdb) next
6               printf("merhaba %d\n", i);
(gdb) next
merhaba 0
5           for(int i=0; i < 10; i++){
(gdb) n      
6               printf("merhaba %d\n", i);
(gdb) n     
merhaba 1
5           for(int i=0; i < 10; i++){
İkinci döngüyü denetlerken sum değişkeninin taşıdığı değerini print sum komutu ile öğrenebiliriz:
(gdb) n
11          for(int i=0; i <= 10; i++){
(gdb) n
12              sum += i;
(gdb) print sum
$1 = 3457025
(gdb) n 
11          for(int i=0; i <= 10; i++){
(gdb) n
12              sum += i;
(gdb) print sum
$2 = 3457027
Aslında buradan anlıyoruz ki sum değişkenini tanımlarken 0 değerinde başlatmalıymışız.

Bazı durumlarda sürekli next yapmak yerine birden fazla breakpoint noktası arasında geçiş yapmak için continue komutu kullanılabilir.

GDB'ye dair çok fazla ayrıntı mevcut bu sebeple hepsini bu yazıda bahsetmem çok zor ancak aşağıya eklediğim bağlantılardan çok daha ayrıntılı bilgilere ulaşabilirsiniz.


Kaynakça:

  1. How to Debug C Program using gdb in 6 Simple Steps [https://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb/]
  2. 9.2 - Debugging - GDB Tutorial [https://www.youtube.com/watch?v=bWH-nL7v5F4]
  3. How do I use the MinGW gdb debugger to debug a C++ program in Windows? [https://stackoverflow.com/questions/4671900/how-do-i-use-the-mingw-gdb-debugger-to-debug-a-c-program-in-windows]


Hiç yorum yok:

Yorum Gönderme