【1】GDB && QString
GDB的print命令仅能打印基本数据类型,而像QString这样的复杂类型就无能为力了!
如果调试时不能看QString的值,很让人抓狂!!!幸好,GDB提供了扩展功能,可以自定义宏命令。
把如下自定义的宏命令放到$HOME/.gdbinit文件中,每次启动GDB时会自动加载。
自定义宏命令内容如下:
1 define printqstring 2 printf "(QString)0x%x (length=%i): \"",&$arg0,$arg0.d->size 3 set $i=0 4 while $i < $arg0.d->size 5 set $c=$arg0.d->data[$i++] 6 if $c < 32 || $c > 127 7 printf "\\u0x%04x", $c 8 else 9 printf "%c", (char)$c10 end11 end12 printf "\"\n"13 end
上面的代码是从坊间摘录的。坊间指导:直接复制到$HOME/.gdbinit文件中就可以。
针对如上指导,问题有二:
1.gdbinit文件找不到怎么办?得先找到gdbinit文件。针对像我这种菜鸟,提示操作如下:
红色框中为gdbinit文件本地实际路径。
2.宏命令添加好后怎么使用呢?
一般使用print命令:print VariableName (简写:p VariableName)
类比使用,针对该宏命令,使用示范:printqstring VariablenName
if 如上操作,的确成功了,请到此为止。否则,请继续往下看。
【2】问题分析
本地使用宏命令过程中发现有问题,提示如下:
"cannot resolve overloaded method `data': no arguments supplied”
异常现象截图如下:
经分析,研究Qt源码QString类过程如下:
1 class Q_CORE_EXPORT QString 2 { 3 public: 4 typedef QStringData Data; 5 // ..... TODO 6 Data *d; 7 // ..... TODO 8 }; 9 10 typedef QTypedArrayDataQStringData;11 12 template 13 struct QTypedArrayData14 : QArrayData15 {16 // ..... TODO17 T *data() { return static_cast (QArrayData::data()); }18 const T *data() const { return static_cast (QArrayData::data()); }19 // ..... TODO20 };21 22 struct Q_CORE_EXPORT QArrayData23 {24 QtPrivate::RefCount ref;25 int size;26 uint alloc : 31;27 uint capacityReserved : 1;28 29 qptrdiff offset; // in bytes from beginning of header30 31 void *data()32 {33 Q_ASSERT(size == 034 || offset < 0 || size_t(offset) >= sizeof(QArrayData));35 return reinterpret_cast (this) + offset;36 }37 38 const void *data() const39 {40 Q_ASSERT(size == 041 || offset < 0 || size_t(offset) >= sizeof(QArrayData));42 return reinterpret_cast (this) + offset;43 }44 // ..... TODO45 };
备注:本地调试QT版本为5.3.2
需要修正命令,如下所述。
【3】修正命令
自定义宏命令内容修改如下(ps: 与上个版本差异仅在第5行):
1 define printqstring 2 printf "(QString)0x%x (length=%i): \"",&$arg0,$arg0.d->size 3 set $i=0 4 while $i < $arg0.d->size 5 set $c=$arg0.d->data()[$i++] 6 if $c < 32 || $c > 127 7 printf "\\u0x%04x", $c 8 else 9 printf "%c", (char)$c10 end11 end12 printf "\"\n"13 end
经验证,效果正常。正常使用示例如下所述。
【4】使用示例
4.1 源码如下:
1 void WinHelpManual::openUrl() 2 { 3 QString Html = m_view_list.selectedHtml(); 4 QString strUrlExp = "outline_[0-9]*.htm"; 5 QRegExp urlRegExp(strUrlExp, Qt::CaseSensitive); 6 if (urlRegExp.indexIn(Html) != -1) 7 { 8 QString strWebUrl = urlRegExp.cap(0); // 匹配到的url 9 m_view_contents.setUrl(QUrl(m_path + strWebUrl));10 }11 }
4.2 正常使用截图如下:
备注:红色框中为字符串值。
【5】利用toStdString()接口
有同事提到可以利用toStdString()接口查看值。
经本地验证,的确可以。但字符串比较长时,打印仍存在问题:
5.1 短字符串,应用示例:
5.2 长字符串,应用示例:
总上所述:建议添加printqstring自定义宏命令,实际应用过程中“因地制宜”。
Good Good Study, Day Day Up.
顺序 选择 循环 总结