GDB(The GNU Project Debugger)中的 print 命令不支持查看 C/C++ Unicode文本變量的內容(wchar_t*)。
假設我們要調試以下 C/C++ 代碼:
int main()
{
const char* szAnsi = "The EF programming language is a general-purpose, simple, easy to use, "
"efficient, practical, object-oriented and cross-platform language. ";
const wchar_t* szUnicode = L"“易語言.飛揚”是一門簡單易學、高效實用、面向對象、跨平臺的計算機通用編程語言。";
return 0;
}
在第 8 行(return 0;)中斷後,可以用 print 命令顯示出 const char* 變量 szAnsi 中的文本內容,但卻無法顯示 const wchar_t* 變量 szUnicode 中的文本內容:
(gdb) b 8 Breakpoint 1, main () at test.cpp:8 |
從上面的執行結果可以看到,print 只能顯示出 wchar_t* 文本變量的地址,並不直接顯示出其中的文本內容,甚至連單個Unicode字符也顯示不出來(只顯示Unicode代碼)。這個就比較討厭了。
在實際調試工作中,迫切需要直接查看Unicode文本變量的內容。我們給出的解決方案是,通過 .gdbinit 文件給 GDB 增加一個 wprint 命令,用於顯示 wchar_t* 變量值。
主要實現原理是,先將Unicode文本內容存儲到一個臨時文件中,然後調用另外一個程序讀取文件內容並顯示出來。
具體操作方法如下:
首先,請將以下內容存儲爲 ~/.gdbinit 文件,或添加到原有文件中:
set $fd = open("/tmp/dywt.gdb.wprint", 577)
set $x = write($fd, $arg0, wcslen($arg0) * sizeof(wchar_t))
set $y = close($fd)
shell dywt.gdb.wprint
end
document wprint
print the content of unicode text variable (wchar_t*)
for example: wprint unicode_text_var_name
end
其中,我們調用了一個外部可執行程序,dywt.gdb.wprint,其 C/C++ 源代碼如下:
#include <memory.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
const char* file_name = "/tmp/dywt.gdb.wprint";
FILE* f = fopen(file_name, "rb");
if(f == 0)
{
printf("Open '%s' error! ", file_name);
return -1;
}
fseek(f, 0, SEEK_END);
long file_size = ftell(f) + 1;
fseek(f, 0, SEEK_SET);
wchar_t* buf = (wchar_t*)malloc(file_size + sizeof(wchar_t));
int r = fread(buf, 1, file_size, f);
buf[file_size / sizeof(wchar_t)] = 0;
printf("%S ", buf);
free(buf);
}
將以上代碼編譯爲可執行程序 dywt.gdb.wprint,複製到 /usr/bin 目錄下即可。
(注:以上實現中,好象不能省略臨時文件 /tmp/dywt.gdb.wprint。GDB中的 $var 採用文本替換機制,即,如果把 $arg0 當作參數傳遞給 dywt.gdb.wprint,實際接收到的是文本 "$arg0" 。)
實際使用中,wprint 用法與 print 完全相同:
(gdb) print szAnsi |
以上是在實踐中摸索出來的方法,不敢私藏,特拿出來與大家分享。應該還有更好的解決方案,我們暫時沒有發現而已,期待高人指點。