Syntax highlighting of Archiv/Ladění pod UNIXEM - gdb, mtrace

==Programy a chyby==
Téměř každý program má svoje chyby. Chyby mohou být jak v návrhu(program tak jak je naržen nefunguje správně),
tak v realizaci (chyby v kódu). Praktičtější je ovšem chyby rozdělit na chyby "aktivní" a pasivní. Do první 
skupiny patří chyby patrné na první pohled, tj. program nedělá to co má, nebo padá. Do druhé skupiny patří typicky
chyby v alokaci a uvolňování paměti. Druhou skupinu je výrazně obtížnější jak detekovat, tak odhalit.
===Fáze ladění kódu===
Vytváření a aldění nového software vpostatě probíhá podle následujícího shématu:
 DOPSAL JSEM SOFTWARE                                                                   
 TESTUJU HO                                                                             
 if (V PROGRAMU JE CHYBA) goto ZACATEK LADENI else goto KONEC                           
  ZACATEK LADENI                                                                       
  STABILIZUJ CHYBU //zajisteni aby se chyba opakovala                                  
  LOKALIZUJ CHYBU  //nalezeni příslušné knihovny, funkce, řádku, kde k chybam dochazi  
  OPRAV CHYBU                                                                          
 goto TESTUJ HO                                                                       
 KONEC //program je odladěný a můžeme začít s distribucí.

===Možnosti ladění kódu===
====Expertní čtení====
Nejjednosušší je tzv "expertní čtení", aneb "Strécu, ono to nefacha, tak se do toho hleď ještě mrknout.". Tohle je jistě
možnost, ale má nevýhodu zejména psychologickou, pokud jsme udělali logickou chybu v návrhu, je poměrně těžké ji 
odstranit jen čtením kódu, protože se ném kód zdá v pořádku. Je to (prý) poměrně funkční v případě, že kód po nás čte 
někdo jiný.
====Ladící výpisy====
Asi nejobecnější možnost ladění, funguje skoro vždy a skoro všude. Je dobré vypisovat na stderr, pač jinak pokud 
něco vypíšete na stdin a program pak "spadne", hláška se může v principu stratit (neměla by, ale experimentálně je 
tohle tvrzení ověřené).
Do programu je možné zařadit výpisy na místa, kde čekáme, že by mohlo dojít k chybě.
Docela rozumné může být využít makroprocesoru překladače, napřiklad konstrukcí 

 #ifdef DEBUG
   printf ("hodnota x je : %d\n", x);
 #endif

a makro DEBUG si definovat třeba při překladu

 $ cc -o sorter -DDEBUG main.c
A jinak v jazyce c/c++  jsou k dispozici makra
{| border=1 cellspacing=0 cellpadding=5
| __LINE__
| Číslo aktuální řádky
|-
| __FILE__
| Jméno souboru
|- 
| __DATE__
| datum, Řetězec formátu "Mmm dd yyyy"
|-
| __TIME__
| čas, Řetězec formátu "h h : mm : s s"
|-  
|}

====Ladící nástroje====
Jsou asi neúčinnější formou ladění, (pokud jsou dostupné), pod unixovými systémy je obvykle k dspozici pro ladění 
chyb, které se projevují db, který má pod linuxem obdobu gdb. Na skryté chyby, např v alokaci paměti jsou k dispozici
nástroje typu mtrace, nebo knihovna electric fence (možná pár slov na konci).
Program gdb nám umožňuje pozorovat co se děje v "programu vevnitř", popřípadě toto dokonce měnit.
==Ukázkový příklad 1.==
main.c

 #include <stdio.h>
 #include <stdlib.h>
 #include "qsort.h"
 int main(int argc, char ** argv){  
  int i;
  int cisla[] = {10, 12, 2, 4, 8,7, 1, 20, 3, 25};
  int *  cilsa;
  int arrsize = sizeof(cisla) / sizeof(int); 
  printf("\n\nhello, Im Program for sorting.. ");
  
  printf("\nthis is my input  :");
  for (i=0; i < arrsize; i++){
    printf("%d ",cisla[i] );
  }
  //tady se to celý děje.
  xquickSort(cilsa,  arrsize);
  
  printf("\nthis is my output :");
  
  for (i=0; i < arrsize; i++){
    printf("%d ",cisla[i] );
  }
  printf("\nDo you think it's OK?\n");
  return 0;
 }

qsort.c
 void xq_sort(int numbers[], int left, int right){
  int pivot, l_hold, r_hold;
  l_hold = left;
  r_hold = right;
  pivot = numbers[left];
  while (left < right)
  {
    while ((numbers[right] >= pivot) && (left < right))
      right--;
    if (left != right)
    {
      numbers[left] = numbers[right];
      left++;
    }
    while ((numbers[left] <= pivot) && (left < right))
      left++;
    if (left != right)
    {
      numbers[right] = numbers[left];
      right--;
    }
  }
  numbers[left] = pivot;
  pivot = left;
  left = l_hold;
  right = r_hold;
  if (left < pivot)
    xq_sort(numbers, left, pivot-1);
  if (right > pivot)
    xq_sort(numbers, pivot+1, right);
 
 }

qsort.h

 extern void xquickSort(int numbers[], int array_size);
Makefile

 EXECUTABLE	        = sorter 
 SOURCES		= main.c qsort.c
 HEADERS		= qsort.h
 OBJECTS		= $(SOURCES:.c=.o)
 CC		        = gcc
 CFLAGS		        = -ggdb -Wall
 LDFLAGS		= -o 
 all: $(EXECUTABLE) 
 clean:
       rm *.o $(EXECUTABLE) 
 $(EXECUTABLE): $(OBJECTS)
       $(CC) $(LDFLAGS) $@ $^
 $(OBJECTS): $(SOURCES) $(HEADERS)


==Překlad programu==
Program se nám přeloží bez chyb nebo varování. Je dobré poznamenat,že program je dobé přeložit s parametrem 
 -g, 
nebo pro gdb ještě lépe 
 -ggdb nebo -ggdb3
. Ty volby se liší ve formátu ladících informací vkládaných do souboru.  Do programu takto budou vkládat i některé informace "navíc",které ladícímu prostředku umožní sledovat hromadu věcí, jako jsou třeba jména proměnných a podobně
Mimo jiné by šlo ještě poznamenat, že pokud program nechodí tak jak má je dobré ho přeložit s volbou 
 -Wall -pedantic -ansi
, které nám mohou pomoci odhalit i některé neobyklé konstrukce, často chyby.

== Nástroj gdb ==
gdb je program pro ladění jiných programů. Programy jdou spustit jakoby "v něm". Někdo tvrdí, že je gdb 
nepřekonatelné... Já bych byl střízlivšjší, pro člověka, který není líný se něco naučit, a je schopen
překonat deprese z příkazové řádky je to mocný nástroj.
=== Co umožňuje gbd ===
Ladit přeložené programy, zkoumat core-dumpy a připojovat se k běžícím programům. Poslední možnost je docela praktická zvlástě pokud chceme ladit třeba serverové aplikace.

=== Co se děje při startu gdb ===
Než začnu rozebírat přikazy pro gdb, pár slov k tomu, co se děje při startu gdb.
#1gdb se rozběhne v příslušném módu (třeba s gui, nebo v módu silent).. (o gui nic netuším ,ale je to v manuálu)přečte si konfigurák v $HOME
#2zpracuje argumenty příkazové žádky
#přečte si konfigurák v aktuálním adresáři
#načte histotii příkazů pokud ji máme zapnutou

=== Konfigurační soubor ===
A teď k tomu konfiguráku: na linuxu se jemnuje vždycky stejně, .gdbinit a dá se do něj nacpat spoooousta zajímavejch věcí.
No třeba ta historie :

 set history filename ./.gdb_history
 set history save on 

Docela dobry je si do konfiguraku v daném adresáři dát který soubor bude laděn
 file ./sorter

Nebo preloudované knihovny
 set env LD_PRELOAD=/usr/lib/libefence.so

Nebo breakpointy
 b main

Dají se tem taky definovat makra, ale to je jiná kapitola.
Komentáře jsou jako ve skriptech - uvozené #

=== Spuštění gdb ===
celá ta nádhera se spustí pomocí příkazu gdb. Volby jsou následující :
{| border=1 cellspacing=0 cellpadding=5
| -s file
|Ze souboru file se načte tabulka symbolů 
|-
| -e file
|Soubor file bude laděn , možno kombinovat se s.
|-
| -c N
|Gdb se připojí k již běžícímu procesu s PID N 
|-
| -c file
|Gdb načte core soubor file 
|-
| -x file
|Gdb vykoná gdb příkazy v souboru file, něco jako možnost skriptování 
|-
| -d dir
|K adresářům, v nichž gdb hledá zdrojové kódy přidá dir 
|-
| -m
|Načte symboly do souboru, který pak používá jako tabulku symbolů 
|-
| -r
|Načte všechny symboly okamžitě, místo čtení až v případě potřeby 
|-
| -n,-nx
|GDB nevykoná žádné příkazy z inicializačních souborů
|-
| -q
|Nevytiskne po spuštění úvodní text a informace o copyrightu 
|-
| -batch
|Po vykonání příkazů v souboru -x file vrátí 0, při chybě vrátí nenulové číslo 
|-
| -cd dir
|Změní aktuální adresář na dir 
|-
| -f
|Vypisuje plné jméno souboru a číslo řádky vždy při zastavení programu 
|-
| -b bps
|Nastaví rychlost seriového portu na bps pro vzdálené ladění 
|-
| -tty dev
|Přesměruje stdout a stdin laděného programu na dev 
|}
Kdo jste chodila na základy překladačů tak určitě víte co jsou to tabulky symbolů.
Je to taková ta chztrá věc, která pojí to jak se proměnná jmenuje, a to jakou má hodnotu.
Docela fajn věc pro takové ladění.

Jinak většinou budete startovat gdb příkazem
 gdb file
, kde file je jméno laděného programu.

=== Příkazy v gdb ===
No a teď zvesela na všechny možný příkazy a fíčury gdb.
příkazy se zadávají ručně a gdb si je kompletuje, tj, pokud stisknete 
 h
a 
 help 
je jediný příkaz začínající na h
tak to gdb pochopí. Pokud mu dáváte ještě vybrat,tj. je víc příkazu začínající danou sadou znaků, tak  gdb vypíše možnosti.

=== Příkaz help ===
První příkaz, který je dobrý znát je vyvolání helpu. 
help se vyvolá třeba 
 h
Tenhle příkaz vypíše seznam všech skupin do kterých jsou příkazy dělené. 
 h <skupina> 
zobrazí příkazy ve skupině.
 h <prikaz>  
zobrazí krátký popis příkazu.
Ukázka:
Chceme se dozvědět jak se nastavuje breakpoint na nějakou řádku.
 (gdb) h
 aliases -- Aliases of other commands
 breakpoints --
 ....
 (gdb) h breakpoints
 awatch -- Set a breakpoint for an expression
 break -- Set a breakpoint at specified line or function
 ....
 (gdb) h break
nám vrátí podrobný popis jak dát breakpoint na řádku

=== Příkazy k použití pro započetí ladění ===
Pokud už nám gdb bìží (a nespustili jsme ho gdb file) tak musíme specifikovat co se vlastnì bude ladit.

{| border=0 cellspacing=0 cellpadding=5
|exec-file file
|otevře file pro ladìní 
|-    
|core-file file
|otevře core file
|- 
|attach pid
|připojí se k procesu pid 
|}

Programu je možné nastavit argumenty a pracovní adresář.

{| border=0 cellspacing=0 cellpadding=5
|set arg
|nastaví argumenty programu
|- 
|show arg
|zobrazí argumenty programu
|- 
|set environment
|nastaví promìnné prostředí
|- 
|show environment
|zobrazí promìnné prostøedí 
|-
|cd dir
|nastaví adresář dir jako aktuální 
|-
|pwd
|zobrazí aktuální adresář
|}

A potom už mùžeme program vesele spustit, a ladit daný program.

{| border=0 cellspacing=0 cellpadding=5
|run
|spustí program 
|}


Ukázka:

 (gdb) exec-file sorter
 (gdb) set arg Evzen
 (gdb) cd ../
 (gdb) run   
Poznámka: když jsem tohle zkoušel tak se mi to jevilo, jako když gdb nenašel v souboru  ladící informace,pokud byl spuštìn bez argumentù a pak mu byl dán pøíkaz exec-file.Že by bug v debuggeru :-) ???

=== Breakpointy, watchpointy a jiné zastavování běhu programu ===
==== Breakpointy ====
==== Watchpointy ====
==== Vyjímky ====
=== Podmínky pro breakpointy, příkazy pro breakpointy ===
=== Zpráva breakpointů (vymazání, disalování) ===
=== Krokování programu ===
=== Zobrazení zdrojového kódu přímo v programu gdb ===
=== Zobrazování kódu programu v asembleru ===
=== Zkoumání obsahu paměti programu ===
==== Formát dat ====
==== Délky datové buňky ====
==== Zobrazování hodnot proměnných (print) ====
==== Automatické zobrazování hodnot proměnných (display) ====
==== Přímý přístup k datům (x, eXamine) ====
=== Práce s daty na zásobníku, trasování ===
=== Ladění proramu v asembleru -pro labužníky ===
=== Proměnné ===
=== Definování maker ===
=== Ukázka session -odladění vzorového příkladu ===