成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

學習使用 GDB 調試代碼

開發 后端
故障排除的麻煩在于它很復雜。GNU調試器 并不是一個特別復雜的應用程序,但如果你不知道從哪里開始,甚至不知道何時和為何你可能需要求助于 GDB來進行故障排除,那么它可能會讓人不知所措。如果你一直使用print、echo或printf語句來調試你的代碼,當你開始思考是不是還有更強大的東西時,那么本教程就是為你準備的。

[[387491]]

使用 GNU 調試器來解決你的代碼問題。

GNU 調試器常以它的命令 gdb 稱呼它,它是一個交互式的控制臺,可以幫助你瀏覽源代碼、分析執行的內容,其本質上是對錯誤的應用程序中出現的問題進行逆向工程。

故障排除的麻煩在于它很復雜。GNU 調試器 并不是一個特別復雜的應用程序,但如果你不知道從哪里開始,甚至不知道何時和為何你可能需要求助于 GDB 來進行故障排除,那么它可能會讓人不知所措。如果你一直使用 print、echo 或 printf 語句來調試你的代碼,當你開始思考是不是還有更強大的東西時,那么本教程就是為你準備的。

有錯誤的代碼

要開始使用 GDB,你需要一些代碼。這里有一個用 C++ 寫的示例應用程序(如果你一般不使用 C++ 編寫程序也沒關系,在所有語言中原理都是一樣的),其來源于 猜謎游戲系列 中的一個例子。

  1. #include <iostream>
  2. #include <stdlib.h> //srand
  3. #include <stdio.h> //printf
  4.  
  5. using namespace std;
  6.  
  7. int main () {
  8.  
  9. srand (time(NULL));
  10. int alpha = rand() % 8;
  11. cout << "Hello world." << endl;
  12. int beta = 2;
  13.  
  14. printf("alpha is set to is %s\n", alpha);
  15. printf("kiwi is set to is %s\n", beta);
  16.  
  17. return 0;
  18. } // main

這個代碼示例中有一個 bug,但它確實可以編譯(至少在 GCC 5 的時候)。如果你熟悉 C++,你可能已經看到了,但這是一個簡單的問題,可以幫助新的 GDB 用戶了解調試過程。編譯并運行它就可以看到錯誤:

  1. $ g++ -o buggy example.cpp
  2. $ ./buggy
  3. Hello world.
  4. Segmentation fault

排除段故障

從這個輸出中,你可以推測變量 alpha 的設置是正確的,因為否則的話,你就不會看到它后面的那行代碼執行。當然,這并不總是正確的,但這是一個很好的工作理論,如果你使用 printf 作為日志和調試器,基本上也會得出同樣的結論。從這里,你可以假設 bug 在于成功打印的那一行之后的某行。然而,不清楚錯誤是在下一行還是在幾行之后。

GNU 調試器是一個交互式的故障排除工具,所以你可以使用 gdb 命令來運行錯誤的代碼。為了得到更好的結果,你應該從包含有調試符號的源代碼中重新編譯你的錯誤應用程序。首先,看看 GDB 在不重新編譯的情況下能提供哪些信息:

  1. $ gdb ./buggy
  2. Reading symbols from ./buggy...done.
  3. (gdb) start
  4. Temporary breakpoint 1 at 0x400a44
  5. Starting program: /home/seth/demo/buggy
  6.  
  7. Temporary breakpoint 1, 0x0000000000400a44 in main ()
  8. (gdb)

當你以一個二進制可執行文件作為參數啟動 GDB 時,GDB 會加載該應用程序,然后等待你的指令。因為這是你第一次在這個可執行文件上運行 GDB,所以嘗試重復這個錯誤是有意義的,希望 GDB 能夠提供進一步的見解。很直觀,GDB 用來啟動它所加載的應用程序的命令就是 start。默認情況下,GDB 內置了一個斷點,所以當它遇到你的應用程序的 main 函數時,它會暫停執行。要讓 GDB 繼續執行,使用命令 continue

  1. (gdb) continue
  2. Continuing.
  3. Hello world.
  4.  
  5. Program received signal SIGSEGV, Segmentation fault.
  6. 0x00007ffff71c0c0b in vfprintf () from /lib64/libc.so.6
  7. (gdb)

毫不意外:應用程序在打印 “Hello world” 后不久就崩潰了,但 GDB 可以提供崩潰發生時正在發生的函數調用。這有可能就足夠你找到導致崩潰的 bug,但為了更好地了解 GDB 的功能和一般的調試過程,想象一下,如果問題還沒有變得清晰,你想更深入地挖掘這段代碼發生了什么。

用調試符號編譯代碼

要充分利用 GDB,你需要將調試符號編譯到你的可執行文件中。你可以用 GCC 中的 -g 選項來生成這個符號:

  1. $ g++ -o debuggy example.cpp
  2. $ ./debuggy
  3. Hello world.
  4. Segmentation fault

將調試符號編譯到可執行文件中的結果是得到一個大得多的文件,所以通常不會分發它們,以增加便利性。然而,如果你正在調試開源代碼,那么用調試符號重新編譯測試是有意義的:

  1. $ ls -l *buggy* *cpp
  2. -rw-r--r--    310 Feb 19 08:30 debug.cpp
  3. -rwxr-xr-x  11624 Feb 19 10:27 buggy*
  4. -rwxr-xr-x  22952 Feb 19 10:53 debuggy*

用 GDB 調試

加載新的可執行文件(本例中為 debuggy)以啟動 GDB:

  1. $ gdb ./debuggy
  2. Reading symbols from ./debuggy...done.
  3. (gdb) start
  4. Temporary breakpoint 1 at 0x400a44
  5. Starting program: /home/seth/demo/debuggy
  6.  
  7. Temporary breakpoint 1, 0x0000000000400a44 in main ()
  8. (gdb)

如前所述,使用 start 命令進行:

  1. (gdb) start
  2. Temporary breakpoint 1 at 0x400a48: file debug.cpp, line 9.
  3. Starting program: /home/sek/demo/debuggy
  4.  
  5. Temporary breakpoint 1, main () at debug.cpp:9
  6. 9       srand (time(NULL));
  7. (gdb)

這一次,自動的 main 斷點可以指明 GDB 暫停的行號和該行包含的代碼。你可以用 continue 恢復正常操作,但你已經知道應用程序在完成之前就會崩潰,因此,你可以使用 next 關鍵字逐行步進檢查你的代碼:

  1. (gdb) next
  2. 10 int alpha = rand() % 8;
  3. (gdb) next
  4. 11 cout << "Hello world." << endl;
  5. (gdb) next
  6. Hello world.
  7. 12 int beta = 2;
  8. (gdb) next
  9. 14 printf("alpha is set to is %s\n", alpha);
  10. (gdb) next
  11.  
  12. Program received signal SIGSEGV, Segmentation fault.
  13. 0x00007ffff71c0c0b in vfprintf () from /lib64/libc.so.6
  14. (gdb)

從這個過程可以確認,崩潰不是發生在設置 beta 變量的時候,而是執行 printf 行的時候。這個 bug 在本文中已經暴露了好幾次(破壞者:向 printf 提供了錯誤的數據類型),但暫時假設解決方案仍然不明確,需要進一步調查。

設置斷點

一旦你的代碼被加載到 GDB 中,你就可以向 GDB 詢問到目前為止代碼所產生的數據。要嘗試數據自省,通過再次發出 start 命令來重新啟動你的應用程序,然后進行到第 11 行。一個快速到達 11 行的簡單方法是設置一個尋找特定行號的斷點:

  1. (gdb) start
  2. The program being debugged has been started already.
  3. Start it from the beginning? (y or n) y
  4. Temporary breakpoint 2 at 0x400a48: file debug.cpp, line 9.
  5. Starting program: /home/sek/demo/debuggy
  6.  
  7. Temporary breakpoint 2, main () at debug.cpp:9
  8. 9       srand (time(NULL));
  9. (gdb) break 11
  10. Breakpoint 3 at 0x400a74: file debug.cpp, line 11.

建立斷點后,用 continue 繼續執行:

  1. (gdb) continue
  2. Continuing.
  3.  
  4. Breakpoint 3, main () at debug.cpp:11
  5. 11 cout << "Hello world." << endl;
  6. (gdb)

現在暫停在第 11 行,就在 alpha 變量被設置之后,以及 beta 被設置之前。

用 GDB 進行變量自省

要查看一個變量的值,使用 print 命令。在這個示例代碼中,alpha 的值是隨機的,所以你的實際結果可能與我的不同:

  1. (gdb) print alpha
  2. $1 = 3
  3. (gdb)

當然,你無法看到一個尚未建立的變量的值:

  1. (gdb) print beta
  2. $2 = 0

使用流程控制

要繼續進行,你可以步進代碼行來到達將 beta 設置為一個值的位置:

  1. (gdb) next
  2. Hello world.
  3. 12  int beta = 2;
  4. (gdb) next
  5. 14  printf("alpha is set to is %s\n", alpha);
  6. (gdb) print beta
  7. $3 = 2

另外,你也可以設置一個觀察點,它就像斷點一樣,是一種控制 GDB 執行代碼流程的方法。在這種情況下,你知道 beta 變量應該設置為 2,所以你可以設置一個觀察點,當 beta 的值發生變化時提醒你:

  1. (gdb) watch beta > 0
  2. Hardware watchpoint 5: beta > 0
  3. (gdb) continue
  4. Continuing.
  5.  
  6. Breakpoint 3, main () at debug.cpp:11
  7. 11 cout << "Hello world." << endl;
  8. (gdb) continue
  9. Continuing.
  10. Hello world.
  11.  
  12. Hardware watchpoint 5: beta > 0
  13.  
  14. Old value = false
  15. New value = true
  16. main () at debug.cpp:14
  17. 14 printf("alpha is set to is %s\n", alpha);
  18. (gdb)

你可以用 next 手動步進完成代碼的執行,或者你可以用斷點、觀察點和捕捉點來控制代碼的執行。

用 GDB 分析數據

你可以以不同格式查看數據。例如,以八進制值查看 beta 的值:

  1. (gdb) print /o beta
  2. $4 = 02

要查看其在內存中的地址:

  1. (gdb) print /o beta
  2. $5 = 0x2

你也可以看到一個變量的數據類型:

  1. (gdb) whatis beta
  2. type = int

用 GDB 解決錯誤

這種自省不僅能讓你更好地了解什么代碼正在執行,還能讓你了解它是如何執行的。在這個例子中,對變量運行的 whatis 命令給了你一個線索,即你的 alpha 和 beta 變量是整數,這可能會喚起你對 printf 語法的記憶,使你意識到在你的 printf 語句中,你必須使用 %d 來代替 %s。做了這個改變,就可以讓應用程序按預期運行,沒有更明顯的錯誤存在。

當代碼編譯后發現有 bug 存在時,特別令人沮喪,但最棘手的 bug 就是這樣,如果它們很容易被發現,那它們就不是 bug 了。使用 GDB 是獵取并消除它們的一種方法。

下載我們的速查表

生活的真相就是這樣,即使是最基本的編程,代碼也會有 bug。并不是所有的錯誤都會導致應用程序無法運行(甚至無法編譯),也不是所有的錯誤都是由錯誤的代碼引起的。有時,bug 是基于一個特別有創意的用戶所做的意外的選擇組合而間歇性發生的。有時,程序員從他們自己的代碼中使用的庫中繼承了 bug。無論原因是什么,bug 基本上無處不在,程序員的工作就是發現并消除它們。

GNU 調試器是一個尋找 bug 的有用工具。你可以用它做的事情比我在本文中演示的要多得多。你可以通過 GNU Info 閱讀器來了解它的許多功能:

  1. $ info gdb

無論你是剛開始學習 GDB 還是專業人員的,提醒一下你有哪些命令是可用的,以及這些命令的語法是什么,都是很有幫助的。

 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2021-07-28 08:53:53

GoGDB調試

2015-08-14 09:21:09

gdb工具調試 Go

2025-03-31 03:25:00

2017-02-06 18:42:37

Linuxgdb程序

2022-07-25 07:57:19

工具代碼調試

2021-06-04 05:18:29

ARM程序Gdbserver

2010-06-04 17:48:20

Linux編程工具

2022-09-15 14:56:12

GDB調試鴻蒙

2023-11-22 13:13:54

多線程死鎖

2009-06-03 14:42:21

Eclipse調試調試Java程序

2022-12-19 10:10:07

GDB命令

2025-06-26 05:00:00

2009-12-04 13:31:50

VS代碼調試

2010-03-26 15:41:39

Python腳本

2017-09-12 15:11:12

Chrome

2019-12-06 14:30:41

GNU調試器GDB修復代碼

2021-07-05 11:00:43

GDB??臻g編程語言

2024-11-25 16:08:57

Python代碼代碼調試

2023-05-04 12:39:27

GDB命令程序

2012-05-21 10:13:05

XCode調試技巧
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 涩涩视频在线观看 | 久久日韩精品一区二区三区 | 超碰免费在线观看 | 91国内外精品自在线播放 | 国产精品一区一区 | 国产三区视频在线观看 | 日韩一区二区三区四区五区 | 国产精品久久国产愉拍 | 精品一区二区三区四区五区 | 欧美中文视频 | 久久久久国产一级毛片高清网站 | 成人欧美一区二区三区 | 亚洲三区在线观看 | 久久亚洲欧美日韩精品专区 | 在线区| 欧美乱淫视频 | 国产精品久久久久久久久大全 | 一级黄色录像毛片 | hsck成人网| 91资源在线| 视频一区二区三区四区五区 | 麻豆久久久久久久久久 | 最新国产精品视频 | 日韩一区二区久久 | 可以免费看的毛片 | 色.com| 日韩二区| 老司机67194精品线观看 | 午夜精品一区二区三区在线视 | 国产真实乱全部视频 | 久久亚洲一区 | 国产激情一区二区三区 | 欧美影院久久 | 国产黄视频在线播放 | 国产精品免费一区二区三区四区 | 亚洲欧美一区二区三区在线 | 欧美淫片| 久久精品亚洲 | av免费看片| 91 久久 | 亚洲精品区 |