【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)$c 10 end 11 end 12 printf "" " 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 QTypedArrayData<ushort> QStringData; 11 12 template <class T> 13 struct QTypedArrayData 14 : QArrayData 15 { 16 // ..... TODO 17 T *data() { return static_cast<T *>(QArrayData::data()); } 18 const T *data() const { return static_cast<const T *>(QArrayData::data()); } 19 // ..... TODO 20 }; 21 22 struct Q_CORE_EXPORT QArrayData 23 { 24 QtPrivate::RefCount ref; 25 int size; 26 uint alloc : 31; 27 uint capacityReserved : 1; 28 29 qptrdiff offset; // in bytes from beginning of header 30 31 void *data() 32 { 33 Q_ASSERT(size == 0 34 || offset < 0 || size_t(offset) >= sizeof(QArrayData)); 35 return reinterpret_cast<char *>(this) + offset; 36 } 37 38 const void *data() const 39 { 40 Q_ASSERT(size == 0 41 || offset < 0 || size_t(offset) >= sizeof(QArrayData)); 42 return reinterpret_cast<const char *>(this) + offset; 43 } 44 // ..... TODO 45 };
备注:本地调试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)$c 10 end 11 end 12 printf "" " 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.
顺序 选择 循环 总结