在Linux項目開發過程中使用命令行GDB進行C++程序STL調試時,會發現輸出的內容很雜亂,真正有用的信息比較難找。
可以從GCC、Clang的官網下載一個GDB的美化插件:
Clang的libcxx可以從https://github.com/llvm/llvm-project/blob/master/libcxx/utils/gdb下載整個libcxx目錄
GCC的libstdc++可以從https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3/python下載整個libstdcxx目錄
下載完成後在用戶主目錄(比如筆者的主目錄爲/home/admin)創建一個gdbscripts目錄,把下載的兩個目錄放在gdbscripts下,結果如下圖所示:
然後再在主目錄創建一個.gdbinit文件,內容如下:
python
import sys
sys.path.insert(0, '/home/admin/gdbscripts')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
from libcxx.printers import register_libcxx_printer_loader
register_libcxx_printer_loader()
end
如果是Windows,則需要設置HOME環境變量:
然後把上面腳本中的路徑由:
‘/home/admin/gdbscripts’
改爲:
C:/Users/Administrator/gdbscripts
這樣就可以使用GDB直觀地輸出GCC的以及Clang的STL容器了。
特別注意,Windows版本的GDB有些版本可能不支持字符編碼轉換,所以在控制檯顯示中文會是亂碼,目前測試過的SysGCC9.1以及MinGW64下的GDB都有這個問題,原MinGW下的GDB沒這個問題,但是調試器有點老了。網上查了一下資料,這篇文章說是在編譯GDB時需要有iconv包,如果沒有,可能導致編譯出來的gdb在顯示unicode字符的時候會變成亂碼。 如果願意自己折騰的話,可以網上查資料自己編譯一個功能完整的GDB版本;不願意折騰的,也可以使用VisualGDB+筆者增強的CSTLTypeVisualizer.dll庫進行可視化調試,參見:VisualGDB可視化調試STL
如果成功加載了libc++的美化輸出插件會有提示:
下面羅列了腳本對一些常用的數據類型的支持對比:
類型 | Clang libcxx | GCC libstdcxx |
---|---|---|
basic_string | 支持 | 支持 |
string | 支持 | 支持 |
tuple | 支持 | 支持 |
unique_ptr | 支持 | 支持 |
shared_ptr | 支持 | 支持 |
weak_ptr | 支持 | 支持 |
bitset | 支持 | 支持 |
deque | 支持 | 支持 |
queue | 支持 | 支持 |
stack | 支持 | 支持 |
priority_queue | 支持 | 支持 |
map | 支持 | 支持 |
multimap | 支持 | 支持 |
set | 支持 | 支持 |
vector | 支持 | 支持 |
__map_iterator | 支持 | 支持 |
__map_const_iterator | 支持 | 支持 |
__tree_iterator | 支持 | 支持 |
__tree_const_iterator | 支持 | 支持 |
fpos | 支持 | 支持 |
unordered_set | 支持 | 支持 |
unordered_multiset | 支持 | 支持 |
unordered_map | 支持 | 支持 |
unordered_multimap | 支持 | 支持 |
__hash_map_iterator | 支持 | 支持 |
__hash_map_const_iterator | 支持 | 支持 |
__hash_iterator | 支持 | 支持 |
__hash_const_iterator | 支持 | 支持 |
pair | 不支持 | 支持 |
forward_list | 不支持 | 支持 |
還有一些GCC支持的,Clang不支持的,這裏就不一一羅列了,詳情請查看源文件。
關於Clang的插件腳本,注意腳本中的一段話:
“”“GDB pretty-printers for libc++.
These should work for objects compiled when _LIBCPP_ABI_UNSTABLE is defined
and when it is undefined.
“””
另外,如果使用Clang編譯器進行編譯,如果使用的是clang的libc++庫,調試版需要定義宏:
_LIBCPP_DEBUG=1
如果使用的是GCC的libstdc++庫,調試版需要定義宏:
_GLIBCXX_DEBUG
否則調試時看不到字符串的值。當然如果使用GCC編譯器,調試版也建議加上。