#include <stdio.h> #include <unistd.h> int main() { int i; for (i = 0; ; ++i) { printf("%d\n", i); sleep(1); } }
使用gcc -O2編譯程序後運行,並在另外一個虛擬終端裏使用gdb attach進程: linux
root@bt:~# gdb -q -p 2569 Attaching to process 2569 Reading symbols from /root/test3...(no debugging symbols found)...done. Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6 (gdb) bt #0 0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6 #1 0x00007fbf605ac210 in sleep () from /lib/libc.so.6 #2 0x00000000004005c8 in main () (gdb) finish Run till exit from #0 0x00007fbf605ac380 in nanosleep () from /lib/libc.so.6 0x00007fbf605ac210 in sleep () from /lib/libc.so.6 (gdb) finish Run till exit from #0 0x00007fbf605ac210 in sleep () from /lib/libc.so.6 0x00000000004005c8 in main () (gdb) ni 0x00000000004005a8 in main () (gdb) 0x00000000004005aa in main () (gdb) 0x00000000004005af in main () (gdb) 0x00000000004005b4 in main () (gdb) 0x00000000004005b6 in main () (gdb) 0x00000000004005b9 in main () (gdb) 0x00000000004005be in main () (gdb) 0x00000000004005c3 in main () (gdb) 0x00000000004005c8 in main () (gdb) 0x00000000004005a8 in main () (gdb) 0x00000000004005aa in main () ...attach會使進程掛起,現象相似於插入了一個臨時斷點。上面的操做中使用了兩次finish命令使程序運行至返回到main()函數中。
對於使用-O2選項編譯的程序,沒法簡單的進行源代碼級別的調試,next/step命令不可用。對於此類程序,能夠使用nexti/stepi命令,它們大致與next/step相同,分別表示步過與步入,不一樣之處在於前者針對單條彙編指令。上述示例中連續使用ni(nexti)命令,從指令地址(rip寄存器值)能夠比較容易的發現死循環,指令地址始終徘徊在0x00000000004005a8-0x00000000004005c8。 shell
這一招數對於後臺daemon程序至關有效。我曾經維護過一個帶有守護進程的deamon程序,對於出現問題的運行中子進程,守護進程會將其殺死重啓,但並不會記錄詳細緣由。一日,某版本頻繁重啓,領導下了死命令:必須在XXX以前解決!因而動用重量級上古神器gdb掛上守護進程,讓運行中子進程自生自滅。。。天可憐見,終於在一週後重現了問題,並使用上述方法確認了死循環問題及其位置。。。 函數
那晚我夢見了花團錦簇。。。 spa