debuging_c
Toto je starší verze dokumentu!
Obsah
Ladění a odvšivování C
Obecné nástroje
ps
- rodič/potomek
- PID (Process ID), PPID (Parent), PGID (Process Group ID leader),
ps axjf | less PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 12052 12540 12540 12540 ? -1 Ss 0 0:00 \_ sshd: flowmon [priv] 12540 12542 12540 12540 ? -1 S 500 0:03 | \_ sshd: flowmon@pts/0 12542 12543 12543 12543 pts/0 24512 Ss 500 0:00 | \_ -bash 12543 24511 24511 12543 pts/0 24512 S 0 0:00 | \_ su 24511 24512 24512 12543 pts/0 24512 S+ 0 0:00 | \_ bash
- vlákna - jeden proces může mít několik vláken. Všechna vlákna mají stejný PID a Parent PID. LWP (Lightweight Processes) je identifikátor vlákna.
ps -eFL | grep "/bin/some" UID PID PPID LWP C NLWP SZ RSS PSR STIME TTY TIME CMD 503 26207 10278 26207 11 4 1455062 4857636 6 Nov15 ? 13:28:28 /bin/something 503 26207 10278 26207 11 4 1455062 4857636 6 Nov15 ? 13:28:28 /bin/something 503 26207 10278 26768 0 4 1455062 4857636 1 Nov15 ? 00:00:00 /bin/something 503 26207 10278 1849 0 4 1455062 4857636 1 Nov18 ? 00:00:00 /bin/something 503 26207 10278 1850 0 4 1455062 4857636 3 Nov18 ? 00:00:00 /bin/something
- start time - datum/čas spuštění procesu. V kombinaci s time nám říka, jak proces dlouho běží a jak moc využívá procesor. Například následující výpis říká, že procesy postgress byly spuštěny 1.12.2013 a na procesoru běžely necelé dvě minuty (přestože teď je už 2.12 9:30). Procesy tedy skoro nic nedělají.
ps -ef | grep postgress UID PID PPID C STIME TTY TIME CMD postgres 7534 4669 0 Dec01 ? 00:01:04 postgres: somebody somebody 127.0.0.1(37573) VACUUM postgres 13828 4669 0 Dec01 ? 00:01:28 postgres: somebody somebody 127.0.0.1(35066) VACUUM postgres 14167 4669 0 Dec01 ? 00:01:11 postgres: somebody somebody 127.0.0.1(60953) VACUUM postgres 16436 4669 0 Dec01 ? 00:01:19 postgres: somebody somebody 127.0.0.1(58098) VACUUM
- proces může mít různé stavy:
- D - Uninterruptible sleep (usually IO). Tyto procesy většinou způsobují I/O waiting.
- S - Interruptible sleep (waiting for an event to complete). Proces není na CPU.
- R - Running or runnable (on run queue).
- existují ještě modifikátory například l (multi-thread) - tedy Rl znamená spuštěný multi-thread process
ps ax | grep postgress PID TTY STAT TIME COMMAND 7534 ? D 1:04 postgres: somebody somebody 127.0.0.1(37573) VACUUM 13828 ? D 1:28 postgres: somebody somebody 127.0.0.1(35066) VACUUM 14167 ? D 1:12 postgres: somebody somebody 127.0.0.1(60953) VACUUM 16436 ? D 1:19 postgres: somebody somebody 127.0.0.1(58098) VACUUM 17723 ? D 1:07 postgres: somebody somebody 127.0.0.1(47033) VACUUM
top
- spotřeba CPU, paměti, …
- pomoci klavesy f lze zapnout/vypnout ruzne sloupecky s info o procesu, napriklad swap
- pomoci < > lze provest trideni podle sloupcu (reverzni trideni R)
- pomoci H lze zapnout zobrazovani threadu
- pomoci 1 lze zapnout vypis vsech CPU jader:
- sloupec %wa je velice dulezity, jde o I/O waiting. Pokud je I/O waiting skoro 100%, tak je system zatizen (nepouzitelny), i kdyz ma CPU %us velice male.
top - 18:20:11 up 83 days, 10:59, 1 user, load average: 0.06, 0.10, 0.09 Tasks: 137 total, 2 running, 135 sleeping, 0 stopped, 0 zombie Cpu0 : 5.1%us, 1.0%sy, 0.0%ni, 92.5%id, 1.0%wa, 0.0%hi, 0.3%si, 0.0%st Cpu1 : 5.2%us, 0.9%sy, 0.0%ni, 93.1%id, 0.7%wa, 0.0%hi, 0.0%si, 0.0%st
- CPU load je specialni hodnota, ktera rika, jak jsou CPU procesory/jadra vyuzivany info.
- u jedno jadroveho CPU:
- CPU load 0.5 znamana, ze procesor 50% casu nic nedela
- CPU load 1.0 znamena, ze procesor je vytizen na 100%
- CPU load vetsi nez 1.0 rika, ze existujici procesy cekajici na procesor. System je pretizen.
- u vice jadrovych je to analogicky, CPU load 4.0 u 4 jadroveho CPU zneman 100% load
- vypis pameti rika:
- pamet celkem (mem total), kolik je ji pouzito (Mem used), kolik je volne (Mem free),
- jak velky je swap (Swap total), kolik ze swapu se pouziva (Swap used), kolik je swapu volneho (Swap free) - swap se casto pouziva i pro uvolneni bloku hlavni pameti, ktere se dlouho nepouzivaly. Nemusi jit tedy o nedostatek hlavni pameti.
- kolik se pouziva jako file system diskova cache (cached) - to je pamet, kterou lze v pripade potreby uvolnit. Je zahrnuta take v Mem used.
Mem: 2059524k total, 1823764k used, 235760k free, 212016k buffers Swap: 1028312k total, 90556k used, 937756k free, 1218500k cached
- vypis procesu dale rika:
- VIRT - veskera pamet adresovana procesem. Kod, data, sdilene knihovny, swap, … . Muze byt vetsi nez je fyzicka pamet. Zapocitava se sem totiz i napriklad adresovani velkych souboru ulozenych ve skutecnosti pouze na disku.
- RES - skutecne spotrebovana pamet. RES = CODE + DATA. %MEM = RES/TOTAL.
- SHR - sdilena pamet, procesy casto sdili pamet.
- TIME - kolik procesoroveho casu proces spotreboval. Vetsinou je nizsi nez doba behu programu (program nema pridelen CPU porad)
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 16069 somebody 20 0 1385m 95m 60m S 10,0 1,2 2:08.56 vlc 22567 somebody 20 0 1889m 274m 97m S 8,3 3,5 131:34.02 gnome-shell 22291 somebody 20 0 324m 129m 58m S 5,7 1,6 71:22.25 Xorg 5685 somebody 20 0 642m 9m 5764 S 3,7 0,1 107:27.06 pulseaudio
lsof
- zobrazí file deskriptory (soubory, sockety, pipe), které má proces aktuálně otevřené
strace
- Nástroj na monitorování systémových volání
- Umožňuje zobrazit, co program dělá (pouze systémová volání). Typicky zde jde vidět zda čeká na nějaké I/O, zda na nečem necyklí, zda nečeká na nějký zámek, …
- Vypisuje vždy systémové volání s argumenty a návratovou hodnotou. Například u operace write je prvním argumentem file deskriptor. File deskriptory je pak možné dohledat přes lsof -p <pid> (fd 1 je typicky stdinout, fd2 je typicky stderr)
- výpis strace je zkrácený na 32 znaků, pokud je potřeba vidět víc, je třeba nastavit větší délku přes strace -s <newlength>
gdb
- umoňuje se navěsit i na běžící proces
- vypíše aktuální instrukci, hodnoty paměti, ..
- výpis backtrace, krokování
gcore
- kompletní dump procesu včetně celé paměti, k pozdější analýze
pmap
- výpis alokované paměti
time
- měření času spušteného procesu
- ukazuje časy
- real - jak dlouho proces skutečně běžel
- user - kolik strávil execution time v user space
- sys - kolik strávil execution time v user space
- příklad
real 2m4.884s user 0m52.677s sys 0m2.528
- pokud real < user, tak proces využívá paralelismus
- (real - (user+sys)) odpovídá I/O waiting (u single thread procesu)
Diagnostika neoprávněného přístupu do paměti
V céčku jsou nejoblibenější chyby typu segmentation fault. Objevují se totiž náhodně, hlavně když si programátor myslí, že už to má určitě dobře
Nástroje
valgrind
- program pro hledání chyb v programu - špatná práce s pamětí.
- dokáže dobře detekovat chyby v přístupu mimo alokovanou paměť
- je pomalý, u komplikovanějšího kódu mrzne.
- má několik rozšíření, například callgrind (vypisuje volání… grafické rozšíření kcachegrind)
address sanitizer
- zpomaluje program méně a umí hledat víc chyb než valgrind
- podpora v gcc od verze 4.8
- podpora v clang od verze 3.3.
- alternativní překladač C/C++.
- měl by překládat rychleji než gcc a obsahuje kontrolu paměti.
Google's tcmalloc heapprofiler
mtrace
- součástí GNU C knihovny
- vyžaduje úpravu zdrojového kódu
- umí detekovat neuvolněnou paměť
Memory not freed:
-----------------
Address Size Caller
0x0000000001b75460 0x4 at /home/bari/Plocha/heaptest/mtrace/badcode-mtrace.c:10
memprof
Dmalloc
vlastní nástroj
- vlastní implementace malloc, free, …
LD_PRELOAD
- umožňuje přepsat funkce poskytované dynamickými knihovnami v programu pomocí načtení jiné knihovny
- z bezpečnostních důvodů
- u programů s nastaveným setuid bitem musí mít i alternativní knihovna nastaven setuid bit
Backtrace
- pro ladění segfault se hodí výpis backtrace, ten můžeme získat zdroj
- úpravou zdrojových kódů, voláním funkce backtrace_symbols_fd pri obsluze signalu sigfault
- spuštěním binárky přes wrapper catchsegv (lze použít i LD_PRELOAD=/lib/libSegFault.so)
- vygenerováním kompletního dumpu paměti nastavením ulimit v terminálu před spuštěním programu
- aby nám výpis vůbec něco řekl, je nutné mít k dispozici debug symboly (překlad adres na proměnné/funkce)
debuging_c.1446131185.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)
