遇到的问题集合(倒序)
7.Qt跨线程访问对象以及QMainWindow的父对象
有两个问题
第一个问题是在qt里,两个继承自QMainWindow的窗口类A和B,有对象A1、B1当我试图在A1的构造函数里:
B1 = new B1(this);
在B的构造函数里,可以通过参数parent取得A1对象,
但是当我尝试在B1的另一个成员函数里使用parent()成员函数取得父对象时,其返回值总是空指针
也许是QMainWindow对象不应该有父对象?查了查也没找到
查看QMainWindow的定义,也没看到复写parent成员函数,另一个parentwidget函数也只是调用parent而已。
最后不得不在B类里添加一个成员指针,指向A类的对象。
第二个问题是跨线程访问QT对象的
需求:在一个异步线程里,从网络上拉取好友列表,然后创建QListWidgetItem条目,把这些条目添加到QListWidget中
同时更新ui的进度条
陷入两难境地:
如果同步执行:那么该窗口的show调用会被阻塞,直到把这些条目都添加进去,并且更新进度条之后才会显示窗口,
也就是说看不见进度条的更新了
如果异步执行:输出窗口里会显示Cannot set parent, new parent is in a different thread之类的报错,
大意就是不在同一个线程操作是禁止的
解决方法参考自:https://blog.csdn.net/u012321968/article/details/108214644
invokeMethod这个方法,会把第二参数的函数,放到第一参数对象所在的线程执行
整个函数还是异步执行的,只不过在这个函数里跨线程操作对象的部分,使用invokeMethod包裹了起来
for (auto it : MdFriendList)
{
QMetaObject::invokeMethod
(
ui.listWidget,
[=]()
{
QListWidgetItem* Item = new QListWidgetItem();
FriendItemClass* widget = new FriendItemClass();
widget->ui.label->setText(it.second.c_str());
widget->ui.label_2->setText(QString::fromLocal8Bit(" 离线"));
Item->setSizeHint(widget->minimumSizeHint());
ui.listWidget->addItem(Item);
ui.listWidget->setItemWidget(Item, widget);
}
);
}
6.QString 到 char * 中文复制的一个问题
问题出现:从qt控件获取输入的一个中文字符串,然后使用strncpy复制到char * 的问题,当字符串没有中文就不会出现,有中文就出现
原来有问题的代码
char dst[100];
int size = ui.lineEdit_4->text().toLocal8Bit().length();
strncpy(dst, ui.lineEdit_4->text().toStdString().c_str(), msg.size );
测试:
控件ui.lineEdit_4输入四个汉字,size为8(打印出来验证过),strncpy后,再打印dst,就会出现乱码
一开始以为编码问题,尝试过ui.lineEdit_4->text().toUtf8() ui.lineEdit_4->text().toLatin1()
以及其他各个和字符集相关的text()成员函数,总是有乱码
但是直接打印ui.lineEdit_4->text().toStdString().c_str()就没有问题
尝试打印ui.lineEdit_4->text().toStdString().length();
同样四个汉字
ui.lineEdit_4->text().toLocal8Bit().length(); 的值是8
ui.lineEdit_4->text().toStdString().length(); 的值是12
多次验证后,确实如此
直接打QT印控件的字节数一个汉字2字节,转成std::string后每个汉字占了3字节
没有问题的代码
char dst[100];
int size = ui.lineEdit_4->text().toStdString().length();
strncpy(dst, ui.lineEdit_4->text().toStdString().c_str(), size);
5.信号处理的一个问题
在link.的对SIGPIPE信号的处理是危险的,详见本问题最后的截图,该截图来自我的另一篇文章。
关于信号的处理内容见第二张图,第一张图中被注释掉的是原来的代码。
关于SIGPIPE的处理,一开始是替换处理过程,后来又改成SIG_IGN,但是SIG_IGN到底算不算一个《信号处理程序》不得而知,也懒得去测了,而且当下这个情况,对SIGPIPE也没有处理的必要,最后就改成了直接阻塞掉它。
4.(已解决)非阻塞套接字遇到的一个问题
一开始想使用非阻塞套接字来进行传输,通过unp第16章描述,如下:
主要问题是:
对于recv,在接收缓冲区没有数据时,EWOULBLOCK错误
对于send,在发送缓冲区满时,EWOULBLOCK错误
书中描述的语义大概是recv和send的返回EWOULBLOCK,导致我一度使用EWOULBLOCK == recv(sock, buf, 1, 0)
来判断,但实际上是recv和send返回-1,而后通过errno来判断:
if( 0 >= recv(sock, buf, 1, 0)
if(EWOULBLOCK == errno)
...
问题发现过程:在接收端打印recv返回值时,出现了有时返回-1,但是连接并未断开,随后有继续收到数据的情况,通过将errno转换为错误信息后得到:Resource temporarily unavailable。之后在链接.中找到答案: 该链接中的描述解决书中的误导。
另外,在最后的测试中,recv在接收缓冲区空的情况下成功判定到了EWOULBLOCK,但是在send发送缓冲区塞满的情况下,send返回了-1值,errno值却是0
2020年9月19日19:17
今天早上突然想起来,recv是在linux测得,send是在win上测的,怪不得结果不一样,经过刚刚验证后,互换平台代码,得出最终结论:
linux平台:非阻塞套接字,send在发送缓冲区满 和 recv在接收缓冲区空时,返回-1,errno被设置为EWOULBLOCK(11)
win平台:非阻塞套接字,send在发送缓冲区满 和 recv在接收缓冲区空时,返回-1,errno值为0
2020年9月20日07:27
3.(已解决)使用pcap发送arp遇到的一个字节对齐问题
刚才使用pcap发送一个arp包,用wireshark抓包,抓的包和预期对不上。
其中源MAC IP、目的MAC IP,只有源MAC是正确的,确信填写的代码没有出错。
目的MAC填全0,但是抓到的包是01-07-00-00-00-00。后来阴差阳错试着把源mac也填到目的mac上试试是个什么情况,抓到如下包:
情况已然有些明了,从源IP字段开始,所有数据之前都被偏移了两个字节。比如源IP地址那里,源IP应该是192.168.1.7,但是1.7却偏移到了目的MAC的位置,而目的mac地址也依次偏移了两个字节。
开始检查定义ARP包的结构:
首先确定了IN_ADDR结构是4字节:
接下来查看整个结构,如以下图1,结构各个成员加起来应该是28字节,但是sizeof出来却是32字节(2+2+1+1+2+6+4+6+4)。
接着我删掉了,源IP和目标IP字段,如图2,这时sizeof之后只有20字节,之前已经确认过IN_ADDR是4字节,删掉了两个IN_ADDR结构却减少了12字节,此时已经确定是字节对齐的问题了:
最后,通过调整成员顺序(图三)或者合并字段(图四),解决字节对齐,sizeof的结构长度已经是28字节(一个arp包长度)了,之后发送的ARP请求包,也在wireshark中抓到了回复包:
2020年8月19日15:16
2.(未解决)远程调试Linux,找不到libnss_dns.so.2和libresolv.so.2
今天看完unp第11章,想着测试一下gethostbyname和getservbyname,但是远程调试(云服务器)的时候,只要一进入这两个函数,就会断点,然后报如下错,找不到libnss_dns.so.2和libresolv.so.2。接着我把这份代码放到本地的一个虚拟机上跑,可执行文件生成了,但是执行的时候,提示大概也是找不到库之类的,也没找到安装他们的方法。截图:
2020年7月19日23:02:11