Python/C++ debug
debug的方式有很多最簡單的方式是打印log,看log,這個的缺點是比較慢,尤其是用加log的方式來縮小懷疑的範圍。因爲這是一個不斷迭代的過程,最主要的原因,一開始不知道代碼哪個地方有問題。只能在所有可能有問題的地方加打印log。然後逐步的縮小懷疑範圍。下邊介紹一種快速的debug方法。
UT debug
什麼是UT
一半正兒八經的公司,一定會設計UT,UT是對單個功能測試的一種手段,相對於C++來說,測試單位是C++類的所有public方法,private方法通過public方法測試。
UT debug
UT的價值是可以發現之前肉眼沒有發現的錯誤。這也是TDD(測試開發驅動)這麼火的一個原因。
現在C++的UT大多都是GTest, Unitest已經很少有人用。GTest現在可以編譯出UT單獨的binary,直接使用gdb調試即可。
gdb binary # no args
gdb --args binary arg1 arg2 # has args.
在gdb內部使用gdb的命令即可。
包括如下常用命令。
# 下一步,不進入函數體
n/next
# 下一步,如果是子函數,那麼進入子函數
s/step
# 繼續運行代碼,直到代碼結束,或者遇到斷點
c/continue
# 打斷點 在main函數的90行打斷點
b main.cpp:90
# 查看當前上下文的變量值
info locals
# 查看當前函數傳入的形參值
info args
NOTE
- 有時候在使用gdb單步調試的時候,會出現明明是下一步,卻出現gdb向回跑的想象。
原因:gcc在編譯代碼的時候加入了優化選項,比如-Os等等,去掉這些編譯選項,重新編譯即可。
SCT debug
什麼是SCT
MT測試的level比UT高,關注點不再是單個的類,而是在類之間的交互上,SCT的測試level比MT高,在整個binary上。
基本上相當於模擬整個binary的運行環境,進行測試。
業界公共一般使用pytest框架,這是一個python語言的框架,用這個框架將測試對象,也就是我們自己的binary 運行起來,然後等待外界輸入,也就是需要的測試交互。
SCT debug
startup binary under pytest
用C++代碼寫成的binary,會在pytest內部啓動。一般使用subprocess模塊啓動:如下命令啓動
self.__proc = subprocess.Popen(self.start_command, shell=True)
start_command:指的是運行自己binary的命令。例如下:
helloWorld arg
當然不僅僅是起來binary,你所有需要啓動這個binary的工作都要在pytest裏面搞定,具體如何使用就需要參照pytest自己的doc.
pytest case
參照pytest的doc寫case。
pytest breakpoint – pdb
首先給pytest的case打斷點, 有兩種方式
- 在case要斷點的位置,加入如下兩行代碼
import pdb
pdb.set_trace()
- 可以在運行pytest case的時候加入–trace選項
pytest --trace test_hello.py
gdb attach
由於我們自己的binary已經在pytest上啓動,也就是說不需要從gdb再次啓動,可以使用gdb attach的方式來attach到這個進程
實現的腳本如下:
gdbhelloworld.py
import os
import subprocess
pid = subprocess.check_output("pgrep helloworld", shell=True).strip()
print(pid)
gdb.execute('file ' + 'path of binary')
gdb.execute('attach ' + pid.decode('ascii'))
解釋:
- 使用pgrep helloworld獲取binary運行的進程號,
- 加載運行的binary來獲取符號表, file + binary
- attach + pid of binary即可
gdbhelloworld
#!/bin/bash
cgdb -x path of gdbhelloworld.py
解釋:
爲了方便使用,加入一個腳本,使用cgdb,方便看到調試代碼上下文。cgdb可以認爲是對gdb的一個封裝。可以一邊調試,一邊方便的看到當前正在運行的代碼上下文
調試
執行順序
- 執行帶有斷點的pytest.
- 然後執行 ./gdbhelloworld
- 在./gdbhelloworld中打斷點,如
b main.cpp:10
- 在3的基礎上輸入c,讓binary持續運行。
- 在pytest的pdb中單步調試,正在合適的時候就會執行到gdb的斷點位置。
- 然後就可以happy的玩耍了。
參考
None